【问题标题】:Use aggregate function to calculate output in data frame使用聚合函数计算数据框中的输出
【发布时间】:2017-04-24 22:16:34
【问题描述】:

我一直在尝试自己,现在在网上搜索了一段时间,stackoverflow 没有成功。我有一个数据框,我从应用条件和选择投影中提取了该数据框,但未能检索到聚合输出。

数据框mydf:

mydf = list()
mydf = cbind(mydf, 
            c("New York", "New York", "San Francisco"),
            c(4000, 7600, 2500),
            c("Bartosz", "Damian", "Maciej"))
mydf = as.data.frame(mydf)
colnames(mydf) = c("city","salary","name")

让我们假设返回的数据帧的给定部分:

subset(mydf, city == "New York", select = c(salary, name))

返回一个数据框,例如:

   salary    name
9    4000 Bartosz
10   7600  Damian

现在我需要根据给定的薪水计算sum,avg 并从上述数据框中选择薪水最低的员工,最好通过修改上述代码使用单行(我猜这是可能的) , 使其返回:

sum: 11600

avg: 5800

至少:4000 巴托兹


我已经尝试过 (1)

subset(mydf, city == "New York", select = sum(salary))

或 (2)

x = subset(mydf, city == "New York", select = salary)
min(x)

还有更多的组合只会产生错误,说明汇总函数仅在数据帧上定义,所有变量都是数字 (2) 或与第一个代码相同的输出,但没有 sum (1)

【问题讨论】:

    标签: r dataframe aggregate


    【解决方案1】:

    问题可能是您的数据框对象实际上包含一堆列表。所以如果你采取

    ny.df = subset(mydf, city == "New York", select = c(salary, name))
    

    那么任何后续工作都需要使用as.numeric 调用来将您的列表转换为向量。这些将为您提供答案:

    sum(as.numeric(ny.df$salary)) # sum
    mean(as.numeric(ny.df$salary)) # avg
    ny.df[which(as.numeric(ny.df$salary) == min(as.numeric(ny.df$salary))),] # row with min salary
    

    或者,您可以将 mydf 定义为向量数据框,而不是列表数据框:

    mydf = data.frame(c("New York", "New York", "San Francisco"),
                  c(4000, 7600, 2500),
                  c("Bartosz", "Damian", "Maciej"))
    colnames(mydf) = c("city","salary","name")
    
    ny.df = subset(mydf, city == "New York", select = c(salary, name))
    sum(ny.df$salary)
    mean(ny.df$salary)
    ny.df[which(ny.df$salary == min(ny.df$salary)),]
    

    【讨论】:

    • 感谢您解释为什么在这种情况下使用列表来构造数据框是一个不好的选择。我决定重新拒绝我的数据框。
    【解决方案2】:

    你的mydf 很奇怪,所以我自己做了。我将mydf 拆分为city,然后通过对每个子组运行必要的操作(均值、求和等)获得必要的数据。

    #DATA
    mydf = structure(list(city = structure(c(1L, 1L, 2L), .Label = c("New York", 
    "San Francisco"), class = "factor"), salary = c(4000, 7600, 2500
    ), name = structure(1:3, .Label = c("Bartosz", "Damian", "Maciej"
    ), class = "factor")), .Names = c("city", "salary", "name"), row.names = c(NA, 
    -3L), class = "data.frame")
    
    do.call(rbind, lapply(split(mydf, mydf$city), function(a)
        data.frame(employee = a$name[which.min(a$salary)], #employee with least salary
                   mean = mean(a$salary), #mean salary
                   sum = sum(a$salary)))) #sum of salary
    #              employee mean   sum
    #New York       Bartosz 5800 11600
    #San Francisco   Maciej 2500  2500
    

    【讨论】:

    • 对于初学者,非常感谢您的努力。我可能提供了误导性信息。我需要单独的查询来计算总和、平均值并选择最少的。三个单独的电话。以总和为例:仅将总工资作为输出。这样解释更好吗?
    • 你说得对,不过,与我在@lebelinoz 回答后想出的相比,这似乎相当复杂。我不知道我的mydf 有多奇怪。无论如何,+1 的努力,谢谢
    • 非常感谢您的帮助。如果您有其他感觉,我向您道歉,并不是那个意思。我一定会在需要时使用这种方法。
    【解决方案3】:

    使用data.table有一个简单快速的解决方案

    library(data.table) 
    
    setDT(mydf)[, .( salary_sum = sum(salary),
                     salary_avg = mean(salary),
                     name = name[which.min(salary)]), by= city]
    
    >             city salary_sum salary_avg    name
    > 1:      New York      11600       5800 Bartosz
    > 2: San Francisco       2500       2500  Maciej
    

    你的数据集:

    mydf = data.frame(city=c("New York", "New York", "San Francisco"),
                      salary=c(4000, 7600, 2500),
                      name=c("Bartosz", "Damian", "Maciej"))
    

    【讨论】:

      【解决方案4】:

      您的数据框在数据框中的列表结构异常,这可能是您的问题。这是一个 dplyr 解决方案(现在已编辑以找到最低工资)

      library(dplyr)
      mydf <- data.frame(
                   city = c("New York", "New York", "San Francisco"),
                   salary = c(4000, 7600, 2500),
                   name = c("Bartosz", "Damian", "Maciej"))
      
      mydf %>% 
        group_by(city) %>%
        mutate(avg = mean(salary),
               sum = sum(salary)) %>%
        top_n(-1, wt = salary) 
      
      #            city salary    name   avg   sum
      #          <fctr>  <dbl>  <fctr> <dbl> <dbl>
      # 1      New York   4000 Bartosz  5800 11600
      # 2 San Francisco   2500  Maciej  2500  2500
      

      【讨论】:

      • 对于初学者,非常感谢您的努力。我可能提供了误导性信息。我需要单独的查询来计算总和、平均值并选择最少的。三个单独的电话。以总和为例:仅将总工资作为输出。这样解释更好吗?
      【解决方案5】:

      我认为 dplyr 是您可能正在寻找的:

         library(dplyr)
         mydf %>% 
         group_by(city) %>% 
         filter (city =="New York") %>%
         summarise(mean(salary), sum(salary))
      
        # A tibble: 1 x 3
        #  city mean(salary) sum(salary)
        #  <fctr>        <dbl>       <dbl>
        #1 New York         5800       11600
      

      这个链接有很好的教程链接[https://rpubs.com/justmarkham/dplyr-tutorial]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-29
        • 1970-01-01
        相关资源
        最近更新 更多