按组计算时间的相对变化

5
我在努力计算一家公司年度净销售额的百分比差异,考虑到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]。 对于公司的第一次观察,sales_change需要设置为1。
我阅读了以下帖子以获取指导,但没有成功。
  1. 在R中按组计算第一差异
    • 计算的是差异而不是百分比变化
  2. 按组和时间匹配计算值之间的差异
    • 调整代码后只得到na
  3. 如何查找列之间的百分比差异并相应命名?
    • 此代码返回不同销售期的新列,由于我使用的是多年,这并不理想
  4. 在R数据框中计算百分比变化
  5. 如何从不同跨度的不同行计算百分比变化
  6. 按组计算相对于基线的时间序列的变化。如果没有测量基线值,则为NA
    • 适用于基线,这不是我要找的
  7. 使用dplyr按组/ id进行滚动平均(移动平均值)
    • 看起来是计算平均值的优雅解决方案,但我正在寻找百分比变化。
对于我提供的示例数据,期望输出将是:
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

我需要一些帮助。提前感谢。
2个回答

6

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

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

在这里,使用:=创建一个新变量,重复第一个月的销售数据,并用tail删除最后一个月份的分母。按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

1
在我看来,这个方法非常好,感谢您的解释。我需要更多地了解data.table和R在全局范围内的可能性。我不知道head可以这样使用。 - Patrick

3

你可以使用 bylpermno 分组后,对你的数据帧应用一个函数。

在分割后,将相对变化公式应用到每个子数据帧的 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"))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接