使用.data.table进行操作:简洁地计算百分比变化

8

我想使用data.table来简洁地计算一些百分比变化,但我在完全理解.SD操作方式方面遇到了一些问题。假设我有以下表格:

dt = structure(list(type = c("A", "A", "A", "B", "B", "B"), Year = c(2000L, 
2005L, 2010L, 2000L, 2005L, 2010L), alpha = c(0.0364325563237498, 
0.0401968159729988, 0.0357395587861466, 0.0317236054181487, 0.0328213742235379, 
0.0294694430578336), beta = c(0.0364325563237498, 0.0401968159729988, 
0.0357395587861466, 0.0317236054181487, 0.0328213742235379, 0.0294694430578336
)), .Names = c("type", "Year", "alpha", "beta"), row.names = c(NA, 
-6L), class = c("data.table", "data.frame"))


> dt
##    type Year      alpha       beta
## 1:    A 2000 0.03643256 0.03643256
## 2:    A 2005 0.04019682 0.04019682
## 3:    A 2010 0.03573956 0.03573956
## 4:    B 2000 0.03172361 0.03172361
## 5:    B 2005 0.03282137 0.03282137
## 6:    B 2010 0.02946944 0.02946944

为了计算每个类别中alpha的百分比变化,我想出了以下代码:
dt[,change:=list(lapply(3:2,function(x)(.SD[x,alpha]/.SD[
(x-1),alpha]))),by=list(type)][][Year==2000,change:=NA]   

但是我觉得可能有更简洁的方法来完成它。特别是如果想要对两列执行百分比变化,下面的方法将不起作用。

dt[,c("changeAlpha","changeBeta"):=list(lapply(3:2,
function(x)(.SD[x]/.SD[(x-1)]))),by=list(type)][Year==2000,change:=NA][]

所以我采取了以下措施:
dt[,c("changeAlpha","changeBeta"):=list(
lapply(3:2,function(x)(.SD[x,alpha]/.SD[(x-1),alpha])),
lapply(3:2,function(x)(.SD[x,beta]/.SD[(x-1),beta]))),by=list(type)][
Year==2000,c("changeAlpha","changeBeta"):=list(NA,NA)][]

##        type Year      alpha       beta       changeAlpha        changeBeta
## 1:    A 2000 0.03643256 0.03643256                NA                NA
## 2:    A 2005 0.04019682 0.04019682  1.10332131557826  1.10332131557826
## 3:    A 2010 0.03573956 0.03573956 0.889114172877617 0.889114172877617
## 4:    B 2000 0.03172361 0.03172361                NA                NA
## 5:    B 2005 0.03282137 0.03282137  1.03460416276522  1.03460416276522
## 6:    B 2010 0.02946944 0.02946944 0.897873527693412 0.897873527693412

但操作似乎是正确的,但出现了很多警告,导致我来到这里。

  • 我的思考方法完全错误还是这种操作的正确方式?
1个回答

10

你可以使用data.table v1.9.6+中的shift函数。

定义你的函数。

myFunc <- function(x) x/shift(x)

选择您想要计算百分比的列

cols <- c("alpha", "beta")

或者,如果你想在除了前两列之外的所有列上运行此操作

cols <- names(dt)[-(1:2)]

对每一列运行该函数

dt[, paste0("change", cols) := lapply(.SD, myFunc), by = type, .SDcols = cols][]
#    type Year      alpha       beta changealpha changebeta
# 1:    A 2000 0.03643256 0.03643256          NA         NA
# 2:    A 2005 0.04019682 0.04019682   1.1033213  1.1033213
# 3:    A 2010 0.03573956 0.03573956   0.8891142  0.8891142
# 4:    B 2000 0.03172361 0.03172361          NA         NA
# 5:    B 2005 0.03282137 0.03282137   1.0346042  1.0346042
# 6:    B 2010 0.02946944 0.02946944   0.8978735  0.8978735

我没有最新版本。代码肯定更简洁,更易读。然而,在安装了最新版本的data.table并运行您的代码后,我得到了“找不到对象'CisOrderedSubset'”。你有什么线索吗? - DJJ
1
关闭所有 R 会话,只打开一个并重新安装。 - David Arenburg
1
顺便提一下,如果你想在数据的所有列上运行此代码,除了前两列之外,请设置cols <- names(dt)[-(1:2)],然后运行代码。 - David Arenburg

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