我试图计算无意中聚合的数据的滞后差异(或实际增加).数据中的每个连续年份包括上一年的值.可以使用以下代码创建示例数据集:
set.seed(1234)
x <- data.frame(id=1:5, value=sample(20:30, 5, replace=T), year=3)
y <- data.frame(id=1:5, value=sample(10:19, 5, replace=T), year=2)
z <- data.frame(id=1:5, value=sample(0:9, 5, replace=T), year=1)
(df <- rbind(x, y, z))
Run Code Online (Sandbox Code Playgroud)
我可以使用lapply()和split()计算每个唯一ID的每年之间的差异的组合,如下所示:
(diffs <- lapply(split(df, df$id), function(x){-diff(x$value)}))
Run Code Online (Sandbox Code Playgroud)
但是,由于diff()函数的性质,第1年的值没有结果,这意味着在我用diffs列表压缩列表后Reduce(),我无法将实际的年度增量添加回数据框,如下所示:
df$actual <- Reduce(c, diffs) # flatten the list of lists
Run Code Online (Sandbox Code Playgroud)
在此示例中,只有10个计算差异或滞后,而数据框中有15行,因此在尝试添加新列时R会引发错误.
如何创建一个新的实际增长列,其中(1)第1年的值和(2)所有后续年份的计算差异/滞后?
这是我最终要寻找的输出.我的diffs列表列表计算了第2年和第3年的实际值.
id value year actual
1 21 3 5
2 26 3 16
3 26 3 14
4 26 3 10
5 29 3 14
1 16 2 10
2 10 2 5
3 12 2 10
4 16 2 7
5 15 2 13
1 6 1 6
2 5 1 5
3 2 1 2
4 9 1 9
5 2 1 2
Run Code Online (Sandbox Code Playgroud)
我认为这对你有用。当您遇到 diff 问题时,只需将 0 作为第一个数字来延长向量即可。
df <- df[order(df$id, df$year), ]
sdf <-split(df, df$id)
df$actual <- as.vector(sapply(seq_along(sdf), function(x) diff(c(0, sdf[[x]][,2]))))
df[order(as.numeric(rownames(df))),]
Run Code Online (Sandbox Code Playgroud)
有很多方法可以做到这一点,但是这个方法相当快并且使用基础。
这是利用聚合来解决此问题的第二种和第三种方法:
总计的:
df <- df[order(df$id, df$year), ]
diff2 <- function(x) diff(c(0, x))
df$actual <- c(unlist(t(aggregate(value~id, df, diff2)[, -1])))
df[order(as.numeric(rownames(df))),]
Run Code Online (Sandbox Code Playgroud)
经过:
df <- df[order(df$id, df$year), ]
diff2 <- function(x) diff(c(0, x))
df$actual <- unlist(by(df$value, df$id, diff2))
df[order(as.numeric(rownames(df))),]
Run Code Online (Sandbox Code Playgroud)
普利尔
df <- df[order(df$id, df$year), ]
df <- data.frame(temp=1:nrow(df), df)
library(plyr)
df <- ddply(df, .(id), transform, actual=diff2(value))
df[order(-df$year, df$temp),][, -1]
Run Code Online (Sandbox Code Playgroud)
它为您提供的最终产品:
> df[order(as.numeric(rownames(df))),]
id value year actual
1 1 21 3 5
2 2 26 3 16
3 3 26 3 14
4 4 26 3 10
5 5 29 3 14
6 1 16 2 10
7 2 10 2 5
8 3 12 2 10
9 4 16 2 7
10 5 15 2 13
11 1 6 1 6
12 2 5 1 5
13 3 2 1 2
14 4 9 1 9
15 5 2 1 2
Run Code Online (Sandbox Code Playgroud)
编辑:避免循环
我可以建议避免循环并将我给您的内容转换为一个函数(by 解决方案对我来说是最容易使用的)并将其应用于您想要的两列。
set.seed(1234) #make new data with another numeric column
x <- data.frame(id=1:5, value=sample(20:30, 5, replace=T), year=3)
y <- data.frame(id=1:5, value=sample(10:19, 5, replace=T), year=2)
z <- data.frame(id=1:5, value=sample(0:9, 5, replace=T), year=1)
df <- rbind(x, y, z)
df <- df.rep <- data.frame(df[, 1:2], new.var=df[, 2]+sample(1:5, nrow(df),
replace=T), year=df[, 3])
df <- df[order(df$id, df$year), ]
diff2 <- function(x) diff(c(0, x)) #function one
group.diff<- function(x) unlist(by(x, df$id, diff2)) #answer turned function
df <- data.frame(df, sapply(df[, 2:3], group.diff)) #apply group.diff to col 2:3
df[order(as.numeric(rownames(df))),] #reorder it
Run Code Online (Sandbox Code Playgroud)
当然,除非您使用以下内容,否则您必须重命名它们transform:
df <- df[order(df$id, df$year), ]
diff2 <- function(x) diff(c(0, x)) #function one
group.diff<- function(x) unlist(by(x, df$id, diff2)) #answer turned function
df <- transform(df, actual=group.diff(value), actual.new=group.diff(new.var))
df[order(as.numeric(rownames(df))),]
Run Code Online (Sandbox Code Playgroud)
这取决于您执行此操作的变量数量。