按组划分的数据帧行差异

时间:2014-02-26 00:13:29

标签: r dataframe difference

我的问题与按组查找数据框中的行差异有关。我尝试过几种方式。这是一个例子。实际数据集长达数百万行。

set.seed(314)
df = data.frame("group_id"=rep(c(1,2,3),3),
            "date"=sample(seq(as.Date("1970-01-01"),Sys.Date(),by=1),9,replace=F),
            "logical_value"=sample(c(T,F),9,replace=T),
            "integer"=sample(1:100,9,replace=T),
            "float"=runif(9))
df = df[order(df$group_id,df$date),]

我通过group_id和date对它进行了排序,以便diff函数可以找到顺序差异,从而导致逻辑,整数和浮点变量的时间顺序差异。我可以很容易地做某种应用(df,2,diff),但我需要group_id。因此,执行apply(df,2,diff)会导致额外的不必要结果。

df
  group_id       date logical_value integer      float
1        1 1974-05-13         FALSE       4 0.03472876
4        1 1979-12-02          TRUE      45 0.24493995
7        1 1980-08-18          TRUE       2 0.46662253
5        2 1978-12-08          TRUE      56 0.60039164
2        2 1981-12-26          TRUE      34 0.20081799
8        2 1986-05-19         FALSE      60 0.43928929
6        3 1983-05-22         FALSE      25 0.01792820
9        3 1994-04-20         FALSE      34 0.10905326
3        3 2003-11-04          TRUE      63 0.58365922

所以我认为我可以通过group_id将我的数据帧拆分为块,并将每个块传递给用户定义的函数:

create_differences = function(data_group){
  apply(data_group, 2, diff)
}

但是我使用代码得到错误:

diff_df = lapply(split(df,df$group_id),create_differences)
 Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] : non-numeric argument to binary operator 

by(df,df$group_id,create_differences)
 Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] : non-numeric argument to binary operator 

作为旁注,数据很好,没有NAs,空值,空格,并且每个group_id至少有2行与之关联。

编辑1:用户alexis_laz正确地指出我的函数需要是sapply(data_group,diff)。

使用此编辑,我得到一个数据框列表(每组一个列表条目)。

编辑2:

预期输出将是差异的组合数据框。理想情况下,我想保留group_id,但如果没有,这不是什么大问题。以下是示例输出应该是:

diff_df
     group_id date logical_value integer     float
[1,]        1 2029             1      41 0.2102112
[2,]        1  260             0     -43 0.2216826
[1,]        2 1114             0     -22 -0.3995737
[2,]        2 1605            -1      26 0.2384713
[1,]        3 3986             0       9 0.09112507
[2,]        3 3485             1      29 0.47460596

2 个答案:

答案 0 :(得分:2)

我认为,你有数百万行,你可以移动到适合小组行动的data.table

library(data.table)
DT <- as.data.table(df)
## this will order per group and per day
setkeyv(DT,c('group_id','date'))
## for all column apply diff
DT[,lapply(.SD,diff),group_id]

# group_id      date logical_value integer       float
# 1:        1 2029 days             1      41  0.21021119
# 2:        1  260 days             0     -43  0.22168257
# 3:        2 1114 days             0     -22 -0.39957366
# 4:        2 1604 days            -1      26  0.23847130
# 5:        3 3987 days             0       9  0.09112507
# 6:        3 3485 days             1      29  0.47460596

答案 1 :(得分:0)

data.table相比,它肯定不会那么快,但下面是使用aggregate的唯一稍微丑陋的基础解决方案:

result <- aggregate(. ~ group_id, data=df, FUN=diff)
result <- cbind(result[1],lapply(result[-1], as.vector))
result[order(result$group_id),]

#  group_id date logical_value integer       float
#1        1 2029             1      41  0.21021119
#4        1  260             0     -43  0.22168257
#2        2 1114             0     -22 -0.39957366
#5        2 1604            -1      26  0.23847130
#3        3 3987             0       9  0.09112507
#6        3 3485             1      29  0.47460596