从同一变量中的多个值计算 R 中的变量
Computing Variables in R from Multiple Values in the Same Variable
假设我们有一个名为 df 的数据集,这个数据集由两个名为 year 和 x1 的变量组成:
year <- c(2000, 2001, 2002, 2003, 2004)
x1 <- c(7, 8, 6, 3, 3)
df <- data.frame(year, x1)
我的任务是根据 x1 计算两个新变量。第一个变量是 cSum,它必须反映过去两年 x1 值的总和。第二个变量是 cMax,它必须反映最近三年中 x1 的最高值。
结果应该是这样的:
year x1 cSum cMax
2000 7
2001 8 15
2002 6 14 8
2003 3 9 8
2004 3 6 6
如何计算上面的 cSum 和 cMax 变量?
谢谢!
使用data.table
:
library(data.table)
setDT(df)
一是曲折;由于 transpose
已优化,此 可能 更快(未经测试):
df[ , cSum := transpose(lapply(transpose(shift(x1, 0:1)), sum))]
df[ , cMax := transpose(lapply(transpose(shift(x1, 0:2)), max))]
shift
本质上是一个滞后运算符;我们需要滞后 0、1 和(对于 cMax
)2 来获取当前和之前的 1(或 2)个周期。
或者:
df[ , cSum := rowSums(do.call(cbind, shift(x1, 0:1)))]
df[ , cMax := do.call(pmax, shift(x1, 0:2))]
两者给出相同的输出:
df
# year x1 cSum cMax
# 1: 2000 7 NA NA
# 2: 2001 8 15 NA
# 3: 2002 6 14 8
# 4: 2003 3 9 8
# 5: 2004 3 6 6
让事情变得混乱的是,当 shift
returns 超过一个延迟时,它 returns a list
;但不幸的是,这个列表是我们需要的转置(我们正在进行按行操作,并且它是以列友好的方式生成的)。第一个选项 transpose
以更易于管理的形式获取列表,然后在 transpose
返回列形式之前进行行操作。
第二个选项将输出转换为数组并对数组进行逐行操作。
这是一种利用滞后算子的方法。本质上,我正在扩充您的数据,以尽量减少对循环的需求。这样做,我增加了使用的内存量。如果您要使用此数据集进行更多时间序列分析,则此方法可能有意义。在答案中,我使用了 zoo
包,这是我最喜欢的时间序列包。但是,还有很多其他的ts
,xts
(一般比zoo
快),...
library(zoo)
year <- c(2000, 2001, 2002, 2003, 2004, 2005)
x1 <- c(7, 8, 6, 3, 3, 6)
df <- data.frame(year, x1)
dfZ <- zoo(df[,-1], order.by = df[,1])
dfZ <- merge(dfZ, lag(dfZ, seq(-1, -2)))
names(dfZ) <- paste0("L", seq(0,2))
dfZ$cSum <- rowSums(dfZ[, c("L0", "L1")])
dfZ$cMax <- apply(dfZ[, c("L0", "L1", "L2")], 1, max)
假设我们有一个名为 df 的数据集,这个数据集由两个名为 year 和 x1 的变量组成:
year <- c(2000, 2001, 2002, 2003, 2004)
x1 <- c(7, 8, 6, 3, 3)
df <- data.frame(year, x1)
我的任务是根据 x1 计算两个新变量。第一个变量是 cSum,它必须反映过去两年 x1 值的总和。第二个变量是 cMax,它必须反映最近三年中 x1 的最高值。
结果应该是这样的:
year x1 cSum cMax
2000 7
2001 8 15
2002 6 14 8
2003 3 9 8
2004 3 6 6
如何计算上面的 cSum 和 cMax 变量?
谢谢!
使用data.table
:
library(data.table)
setDT(df)
一是曲折;由于 transpose
已优化,此 可能 更快(未经测试):
df[ , cSum := transpose(lapply(transpose(shift(x1, 0:1)), sum))]
df[ , cMax := transpose(lapply(transpose(shift(x1, 0:2)), max))]
shift
本质上是一个滞后运算符;我们需要滞后 0、1 和(对于 cMax
)2 来获取当前和之前的 1(或 2)个周期。
或者:
df[ , cSum := rowSums(do.call(cbind, shift(x1, 0:1)))]
df[ , cMax := do.call(pmax, shift(x1, 0:2))]
两者给出相同的输出:
df
# year x1 cSum cMax
# 1: 2000 7 NA NA
# 2: 2001 8 15 NA
# 3: 2002 6 14 8
# 4: 2003 3 9 8
# 5: 2004 3 6 6
让事情变得混乱的是,当 shift
returns 超过一个延迟时,它 returns a list
;但不幸的是,这个列表是我们需要的转置(我们正在进行按行操作,并且它是以列友好的方式生成的)。第一个选项 transpose
以更易于管理的形式获取列表,然后在 transpose
返回列形式之前进行行操作。
第二个选项将输出转换为数组并对数组进行逐行操作。
这是一种利用滞后算子的方法。本质上,我正在扩充您的数据,以尽量减少对循环的需求。这样做,我增加了使用的内存量。如果您要使用此数据集进行更多时间序列分析,则此方法可能有意义。在答案中,我使用了 zoo
包,这是我最喜欢的时间序列包。但是,还有很多其他的ts
,xts
(一般比zoo
快),...
library(zoo)
year <- c(2000, 2001, 2002, 2003, 2004, 2005)
x1 <- c(7, 8, 6, 3, 3, 6)
df <- data.frame(year, x1)
dfZ <- zoo(df[,-1], order.by = df[,1])
dfZ <- merge(dfZ, lag(dfZ, seq(-1, -2)))
names(dfZ) <- paste0("L", seq(0,2))
dfZ$cSum <- rowSums(dfZ[, c("L0", "L1")])
dfZ$cMax <- apply(dfZ[, c("L0", "L1", "L2")], 1, max)