R:按组和添加的差异

R:按组和添加的差异,r,dataframe,row,R,Dataframe,Row,我想知道如何做这个操作更简单。 假设我有一个像这样的data.frame: set.seed(1) ID <- rep(1:3,each=4) XX <- round(runif(12),3) TT <- rep(1:4, 3) ZZ <- ave(XX*TT,ID, FUN = cumsum) DF <- data.frame(ID, XX, ZZ) ID TT XX ZZ 1 1 0.266 0.266 1 2 0.37

我想知道如何做这个操作更简单。 假设我有一个像这样的data.frame:

set.seed(1)
ID <- rep(1:3,each=4)
XX <- round(runif(12),3)
TT <- rep(1:4, 3)
ZZ <- ave(XX*TT,ID, FUN = cumsum)
DF <- data.frame(ID, XX,  ZZ)   

ID  TT   XX    ZZ
1    1   0.266 0.266
1    2   0.372 1.010
1    3   0.573 2.729
1    4   0.908 6.361
2    1   0.202 0.202
2    2   0.898 1.998
2    3   0.945 4.833
2    4   0.661 7.477
3    1   0.629 0.629
3    2   0.062 0.753
3    3   0.206 1.371
3    4   0.177 2.079
我试过了

ave(DF[3:4],DF$ID,FUN=function(x) diff(c(0,x)))
但它不起作用,它会产生错误:

 Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] : 
  non-numeric argument to binary operator 
这不是一个简单的方法吗? 我发现我可以通过以下方式获得正确的输出:

ave(DF[3:4],DF$ID,FUN=function(x) 
  sapply(x, FUN=function(y) diff(c(0,y))))
但对于一个如此简单的操作来说,它变得相当长和复杂。 我发现我也可以通过使用data.table来实现,但我更喜欢使用base R

setDT(DF)
DF[, lapply(.SD, FUN=function(x) diff(c(0,x)) ), keyby = ID ]
我也不知道如何在每个组的开头插入一行大量的零,或者给定一些条件

ID   XX    ZZ
1     0     0
1 0.266 0.266
1 0.372 1.010
1 0.573 2.729
1 0.908 6.361
2     0     0
2 0.202 0.202
2 0.898 1.998
2 0.945 4.833
2 0.661 7.477
3     0     0
3 0.629 0.629
3 0.062 0.753
3 0.206 1.371
3 0.177 2.079
我试过:

ave(DF[3:4],DF$ID,FUN=function(x) sapply(x, FUN=function(y) (c(0,y))))   
警告:

data length [10] is not a sub-multiple or multiple of the number of
rows [4]
我想一般的方法是使用行的索引

我已经更新了帖子

为了简化操作,我删除了TT列,但我已经注意到这一点很重要

我的解决方案假设表是按TT排序的,但有时不是这样。 我真正想要的是:

XX1
XX2-XX1
XX3-XX2
XX4-XX3
我们不是从表上的位置而是从T得到子索引。
我不知道首先通过TT对列进行排序还是通过创建粘贴语法更有效。

我认为您需要在相关列中使用Lappy,因为ave在其第一个参数中不会使用列表。试试这个:

df[-1] <- lapply(
    df[-1], 
    function(x) ave(x, df$ID, FUN = function(x) c(x[1], diff(x)))
)
数据:


我认为您需要在相关列中使用lappy,因为ave不会在其第一个参数中使用列表。试试这个:

df[-1] <- lapply(
    df[-1], 
    function(x) ave(x, df$ID, FUN = function(x) c(x[1], diff(x)))
)
数据:


下面是在data.table中执行此操作的简单方法


下面是在data.table中执行此操作的简单方法

这里有一个使用dplyr的选项

这里有一个使用dplyr的选项


>是的,我错过了。刚刚更新。但这只是一个例子。伙计们,我的第二个问题有一个简单的解决方案吗?在每组开头或给定位置添加一行。在一篇文章中包含两个独立的问题通常不是一个好主意。如果下面的任何帖子回答了你的第一个问题,我会将第二个问题从这篇帖子中完全删除,并将其作为一个单独的问题发布。然后选择下面的最佳答案。我看到过与您作为第二个问题提出的问题类似的问题,因此在发布之前可能值得搜索一下。>ZZ是的,我错过了。刚刚更新。但这只是一个例子。伙计们,我的第二个问题有一个简单的解决方案吗?在每组开头或给定位置添加一行。在一篇文章中包含两个独立的问题通常不是一个好主意。如果下面的任何帖子回答了你的第一个问题,我会将第二个问题从这篇帖子中完全删除,并将其作为一个单独的问题发布。然后选择下面的最佳答案。我看到过与你作为第二个问题提出的问题类似的问题,所以在发布之前可能值得搜索一下。
   ID     XX    ZZ
1   1  0.266 0.266
2   1  0.106 0.744
3   1  0.201 1.719
4   1  0.335 3.632
5   2  0.202 0.202
6   2  0.696 1.796
7   2  0.047 2.835
8   2 -0.284 2.644
9   3  0.629 0.629
10  3 -0.567 0.124
11  3  0.144 0.618
12  3 -0.029 0.708
df <- structure(list(ID = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 
3L, 3L), XX = c(0.266, 0.372, 0.573, 0.908, 0.202, 0.898, 0.945, 
0.661, 0.629, 0.062, 0.206, 0.177), ZZ = c(0.266, 1.01, 2.729, 
6.361, 0.202, 1.998, 4.833, 7.477, 0.629, 0.753, 1.371, 2.079
)), .Names = c("ID", "XX", "ZZ"), class = "data.frame", row.names = c(NA, 
-12L))
set.seed(1)
ID <- rep(1:3, each=4)
XX <- round(runif(12), 3)
##ZZ <- ave(XX*TT,ID, FUN = cumsum) #we don't have TT
DF <- data.table(ID, XX)

DF[,XX_dif:=XX-c(0,head(XX,length(XX)-1)),by=ID]
# or alternatively using shift()
# DF[, XX_dif := XX-shift(XX, fill=0L), by=ID]

    ID    XX XX_dif
 1:  1 0.266  0.266
 2:  1 0.372  0.106
 3:  1 0.573  0.201
 4:  1 0.908  0.335
 5:  2 0.202  0.202
 6:  2 0.898  0.696
 7:  2 0.945  0.047
 8:  2 0.661 -0.284
 9:  3 0.629  0.629
10:  3 0.062 -0.567
11:  3 0.206  0.144
12:  3 0.177 -0.029
library(dplyr)
DF %>% 
   group_by(ID) %>%
   mutate(ZZ = c(ZZ[1], diff(ZZ)))
#      ID    XX    ZZ
#    <int> <dbl> <dbl>
#1      1 0.266 0.266
#2      1 0.372 0.744
#3      1 0.573 1.719
#4      1 0.908 3.632
#5      2 0.202 0.202
#6      2 0.898 1.796
#7      2 0.945 2.835
#8      2 0.661 2.644
#9      3 0.629 0.629
#10     3 0.062 0.124
#11     3 0.206 0.618
#12     3 0.177 0.708