我的问题与按组查找数据框中的行差异有关。我尝试过几种方式。这是一个例子。实际数据集长达数百万行。
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
答案 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