【问题标题】:Calculate relative change in time by group按组计算时间的相对变化
【发布时间】:2019-06-23 12:51:54
【问题描述】:

我正在努力计算公司年净销售额之间的百分比差异,并考虑到 NA。

以下是数据示例:

dt <- data.table(lpermno = c(10065, 10065, 10065, 10065, 59328, 61241, 59328, 61241, 59328, 61241, 59328, 61241), fyear = c(2001, 2002, 2003, 2004, 2001, 2001, 2002, 2002, 2003, 2003, 2004, 2004), sale = c(NA, NA, NA, NA, 26539, 3891.754, 26764, 2697.029, 30141, 3519.168, 34209, 5001.435))

lpermno fyear sale
10065   2001    NA
10065   2002    NA
10065   2003    NA
10065   2004    NA
59328   2001    26539.000
59328   2002    26764.000
59328   2003    30141.000
59328   2004    34209.000
61241   2001    3891.754
61241   2002    2697.029
61241   2003    3519.168
61241   2004    5001.435

我想计算一个名为 sales_change 的新变量。这个变量应该是出售的百分比变化。 [sale_n]/[sale_n-1] for each company. 对于公司的第一次观察,sales_change 需要只有 1。

我已阅读以下帖子以获得指导,但没有成功。

  1. Calculate first difference by group in R
    • 计算差异而不是百分比变化
  2. Calculate difference between values by group and matched for time
    • 调整代码后仅获取 na 作为输出
  3. R: how to find percent diff between columns and naming accordingly?
    • 此代码返回不同销售期间的新列,因为我已经使用了很多年,这不是可取的
  4. Calculate percentage change in an R data frame
  5. How to calculate percentage change from different rows over different spans
  6. Calculate relative changes in a time series with respect to a baseline by group. NA if no baseline value was measured
    • 使用基线,这不是我想要的
  7. Rolling mean (moving average) by group/id with dplyr
    • 看起来是计算平均值的优雅解决方案,但我正在寻找百分比变化。

对于我上面给出的示例数据,所需的输出是:

output <- data.table(lpermno = c(10065, 10065, 10065, 10065, 59328, 59328, 59328, 59328, 61241, 61241, 61241, 61241), fyear = c(2001, 2002, 2003, 2004, 2001, 2002, 2003, 2004, 2001, 2002, 2003, 2004), sale = c(NA, NA, NA, NA, 3891.754, 2697.029, 3519.168, 5001.435, 26539, 26764, 30141, 34209), output = c(NA, NA, NA, NA, 1, 0.693011, 1.304831, 1.421198, 1, 1.008478, 1.126177, 1.134966))

lpermno fyear sale output
10065   2001    NA  NA
10065   2002    NA  NA
10065   2003    NA  NA
10065   2004    NA  NA
59328   2001    3891.754    1.000000
59328   2002    2697.029    0.693011
59328   2003    3519.168    1.304831
59328   2004    5001.435    1.421198
61241   2001    26539.000   1.000000
61241   2002    26764.000   1.008478
61241   2003    30141.000   1.126177
61241   2004    34209.000   1.134966

我将不胜感激。提前致谢。

【问题讨论】:

    标签: r dataframe grouping


    【解决方案1】:

    使用data.table,您可以执行以下操作:

    dt[, pctchnge := sale / c(sale[1], head(sale, -1)), by="lpermno"][order(lpermno)]
    

    在这里,使用:= 创建一个新变量,重复销售的第一个月,并去掉最后一个月的尾部作为分母。通过 lpermno 执行计算。然后按 lpermno 排序。

    返回

        lpermno fyear      sale  pctchnge
     1:   10065  2001        NA        NA
     2:   10065  2002        NA        NA
     3:   10065  2003        NA        NA
     4:   10065  2004        NA        NA
     5:   59328  2001 26539.000 1.0000000
     6:   59328  2002 26764.000 1.0084781
     7:   59328  2003 30141.000 1.1261770
     8:   59328  2004 34209.000 1.1349657
     9:   61241  2001  3891.754 1.0000000
    10:   61241  2002  2697.029 0.6930112
    11:   61241  2003  3519.168 1.3048314
    12:   61241  2004  5001.435 1.4211981
    

    【讨论】:

    • @Imo 这很好用,谢谢你的解释。我必须更多地了解 data.table 和 R 在全球范围内的可能性。不知道 head 可以用这种方式。
    【解决方案2】:

    您可以使用by 将函数应用于由lpermno 拆分的数据框。

    拆分时,相对变化公式应用于每个子数据帧的sales 列,这些子数据帧由cbind 与新的output 列组合。使用if,我们控制anyNA 的情况并抛出NA,因为无法计算出有意义的平均值。使用do.call(rbind),我们将数据框重新组合在一起。

    do.call(rbind, by(dt, dt$lpermno, function(x)
      if (anyNA(x$sale)) return(cbind(x, output=NA))
      else return (cbind(x, output=c(1, 1/x$sale[-length(x$sale)]*c(x$sale[-1]))))))
    #     lpermno fyear      sale    output
    #  1:   10065  2001        NA        NA
    #  2:   10065  2002        NA        NA
    #  3:   10065  2003        NA        NA
    #  4:   10065  2004        NA        NA
    #  5:   59328  2001 26539.000 1.0000000
    #  6:   59328  2002 26764.000 1.0084781
    #  7:   59328  2003 30141.000 1.1261770
    #  8:   59328  2004 34209.000 1.1349657
    #  9:   61241  2001  3891.754 1.0000000
    # 10:   61241  2002  2697.029 0.6930112
    # 11:   61241  2003  3519.168 1.3048314
    # 12:   61241  2004  5001.435 1.4211981
    

    数据

    dt <- structure(list(lpermno = c(10065, 10065, 10065, 10065, 59328, 
    61241, 59328, 61241, 59328, 61241, 59328, 61241), fyear = c(2001, 
    2002, 2003, 2004, 2001, 2001, 2002, 2002, 2003, 2003, 2004, 2004
    ), sale = c(NA, NA, NA, NA, 26539, 3891.754, 26764, 2697.029, 
    30141, 3519.168, 34209, 5001.435)), row.names = c(NA, -12L), class = c("data.table", 
    "data.frame"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多