【问题标题】:Sum columns row-wise based on IDs in another vector根据另一个向量中的 ID 逐行求和列
【发布时间】:2017-05-04 14:22:27
【问题描述】:

我有两个输入数据框,第一个称为“Firms_Ind”,包含 2 列(“Firms”、“Industry”)和多行。它给出了每个公司的行业 ID。另一个称为“ann_returns”,它的列数与“Firms_Ind”的行数和多行数一样多。它包含每个公司(列)每年(行)的回报。

我想计算每个行业的年平均回报率。所以我想要一个具有以下维度的输出矩阵:列数=年数和行数=年数。对于每个行业(列),应计算每年的平均回报。

这是一个小例子:

> Firms_Ind
  Firms Industry
1     A        1
2     B        2
3     C        3
4     D        1
5     E        2
6     F        1

> ann_returns
      A    B    C    D    E    F
y1 0.20 0.11 0.13 0.30 0.24 0.03
y2 0.23 0.08 0.03 0.23 0.17 0.01
y3 0.28 0.19 0.11 0.21 0.19 0.07

> Industry_mean
            1    2    3
y1_means 0.20 0.11 0.13
y2_means 0.23 0.08 0.03
y3_means 0.28 0.19 0.11

【问题讨论】:

  • 您是否尝试过将ann_returns 重塑为长格式,然后将Firms_Ind 合并到其中,然后按行业分组计算平均值?

标签: r dataframe aggregate


【解决方案1】:

使用dplyrtidyr

library(tidyr)
library(dplyr)

Industry_mean <- ann_returns %>% 
         gather(key=Firms,value=value,-Year) %>% #convert to long format
         left_join(Firms_Ind) %>% #merge with firms_ind
         group_by(Year,Industry) %>% #group as required
         summarise(mean=mean(value)) %>% #calculate means
         spread(key=Industry,value=mean) #convert back to wide format

Industry_mean

   Year       `1`   `2`   `3`
* <chr>     <dbl> <dbl> <dbl>
1    y1 0.1766667 0.175  0.13
2    y2 0.1566667 0.125  0.03
3    y3 0.1866667 0.190  0.11

【讨论】:

    【解决方案2】:

    这是sapply的一种方法

    # get a list of firms by industry
    inds <- split(Firms_Ind$Firms, Firms_Ind$Industry)
    # loop through industries to calculate annual means
    myMat <- sapply(inds,
                  function(i) if(length(i) > 1) rowMeans(ann_returns[, i]) else ann_returns[, i])
    

    在这里,sapply 循环遍历各个行业。对于每个行业,检查是否有多个公司,如果有,申请rowMeans,如果没有,返回原值。

    返回

    myMat
               1     2    3
    y1 0.1766667 0.175 0.13
    y2 0.1566667 0.125 0.03
    y3 0.1866667 0.190 0.11
    

    数据

    Firms_Ind <-
    structure(list(Firms = structure(1:6, .Label = c("A", "B", "C", 
    "D", "E", "F"), class = "factor"), Industry = c(1L, 2L, 3L, 1L, 
    2L, 1L)), .Names = c("Firms", "Industry"), class = "data.frame", row.names = c("1", 
    "2", "3", "4", "5", "6"))
    
    ann_returns <- 
    structure(c(0.2, 0.23, 0.28, 0.11, 0.08, 0.19, 0.13, 0.03, 0.11, 
    0.3, 0.23, 0.21, 0.24, 0.17, 0.19, 0.03, 0.01, 0.07), .Dim = c(3L, 
    6L), .Dimnames = list(c("y1", "y2", "y3"), c("A", "B", "C", "D", 
    "E", "F")))
    

    【讨论】:

    • 谢谢!这似乎是我正在寻找的解决方案。但是,如果我使用我的实际数据框运行它,则会出现以下错误:[.data.frame(ROE_ac, , i) 中的错误:选择了未定义的列我的数据框:ann_returns is ROE_ac (R=305, C = 2) and Firms_Ind是公司_FF (R=30, C = 305)
    【解决方案3】:

    我们可以按列拆分ann_returns,然后运行rowMeans

    # if Firms in correct order
    inds <- split.default(ann_returns, f = Firms_Ind$Industry)
    
    # # if Firms not in correct order:
    # inds <- split.default(
    #     ann_returns,
    #     f = Firms_Ind$Industry[match(colnames(ann_returns), Firms_Ind$Firms)])
    
    do.call(cbind, lapply(inds,rowMeans))
    #            1     2    3
    # y1 0.1766667 0.175 0.13
    # y2 0.1566667 0.125 0.03
    # y3 0.1866667 0.190 0.11
    

    两个输入data.frames是:

    # > dput(ann_returns)
    structure(list(A = c(0.2, 0.23, 0.28), B = c(0.11, 0.08, 0.19
    ), C = c(0.13, 0.03, 0.11), D = c(0.3, 0.23, 0.21), E = c(0.24, 
    0.17, 0.19), F = c(0.03, 0.01, 0.07)), .Names = c("A", "B", "C", 
    "D", "E", "F"), row.names = c("y1", "y2", "y3"), class = "data.frame")
    # > dput(Firms_Ind)
    structure(list(Firms = structure(1:6, .Label = c("A", "B", "C", 
    "D", "E", "F"), class = "factor"), Industry = c(1L, 2L, 3L, 1L, 
    2L, 1L)), .Names = c("Firms", "Industry"), class = "data.frame", row.names = c("1", 
    "2", "3", "4", "5", "6"))
    

    【讨论】:

    • 谢谢!如果公司的顺序正确,你的意思是什么?
    • @Tobi1990,我的意思是ann_returns的列名是否与Firms_Ind的Firm列顺序一致,这样你就可以直接拆分,不用先匹配Firm名称。
    • 是的。再次感谢,您的解决方案完美运行!
    • 你能告诉我如何创建一个新的数据框,其中包含行业中每个公司的计算行业平均值。所以类似于 ann_returns,但对于同一行业的公司具有相同的值:例如,第一年的 A、D 和 F 将是 0.1766667
    • 你可以试试res &lt;- Industry_mean[, Firms_Ind$Industry]; colnames(res) &lt;- Firms_Ind$Frims
    猜你喜欢
    • 1970-01-01
    • 2023-01-24
    • 2012-02-10
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 2022-11-18
    • 2014-09-27
    • 1970-01-01
    相关资源
    最近更新 更多