我有多个数据框,例如:
DG = data.frame(y=c(1,3), v=3:8, x=c(4,6))
DF = data.frame(y=c(1,3), v=3:8, x=c(12,14))
DT = data.frame(y=c(1,3), v=3:8, x=c(4,5))
head(DG)
y v x
1 1 3 4
2 3 4 6
3 1 5 4
4 3 6 6
5 1 7 4
6 3 8 6
head(DT)
y v x
1 1 3 4
2 3 4 5
3 1 5 4
4 3 6 5
5 1 7 4
6 3 8 5
head(DF)
y v x
1 1 3 12
2 3 4 12
3 1 5 12
4 3 6 12
5 1 7 12
6 3 8 12
我想计算每个“行”的均值,但要从每个数据帧的每一列,即我需要的结果数据帧看起来像这样:
y v x
1 'mean(DG(y1)DT(y1),DF(y1))' 'mean(DG(v1)DT(v1),DF(v1))' 'mean(DG(x1)DT(x1),DF(x1))'
2 'mean(DG(y2)DT(y2),DF(y2))' 'mean(DG(v2)DT(v2),DF(v2))' 'mean(DG(x2)DT(x2),DF(x2))'
3 'mean(DG(y3)DT(y3),DF(y3))' 'mean(DG(v3)DT(v3),DF(v3))' 'mean(DG(x3)DT(x3),DF(x3))'
....
实际上,y
,v
和x
是不同的位置,并且是1-6个时间步长。我想平均每个时间步长和位置的数据。最终,我需要一个数据集,看起来像示例数据集之一,但每个单元格中都有平均值。
我有一个带有循环的有效示例,但是对于大型数据集,它非常慢,因此我尝试了套用apply和rowSums的各种组合,但都没有解决。
答案 0 :(得分:1)
如果我理解正确,那么会有许多数据帧,它们都具有相同的结构(数量,名称和列的类型)以及相同的行数(时间步长)。一些数据点可能包含NA。
下面的代码从单个数据帧创建一个大的data.table,并计算不同数据帧中每个时间步长和位置的平均值:
library(data.table)
rbindlist(list(DG, DF, DT), idcol = TRUE)[
, lapply(.SD, mean, na.rm = TRUE), by = .(time_step = rowid(.id))]
time_step y v x 1: 1 1 3 6.666667 2: 2 3 4 8.333333 3: 3 1 5 6.666667 4: 4 3 6 8.333333 5: 5 1 7 6.666667 6: 6 3 8 8.333333
这也适用于NA,例如
DG = data.frame(y=c(1,3), v=3:8, x=c(4,6))
DF = data.frame(y=c(1,3), v=3:8, x=c(12,14))
DT = data.frame(y=c(1,3), v=3:8, x=c(4,5,NA))
请注意,x
的列DT
已被修改
rbindlist(list(DG, DF, DT), idcol = TRUE)[
, lapply(.SD, mean, na.rm = TRUE), by = .(time_step = rowid(.id))]
time_step y v x
1: 1 1 3 6.666667
2: 2 3 4 8.333333
3: 3 1 5 8.000000
4: 4 3 6 8.000000
5: 5 1 7 7.000000
6: 6 3 8 10.000000
请注意,第3行和第6行中的x
已更改。
答案 1 :(得分:0)
如果只有三个数据框,我建议
result = (DG + DT + DF) / 3
result
# y v x
# 1 1 3 6.666667
# 2 3 4 8.333333
# 3 1 5 6.666667
# 4 3 6 8.333333
# 5 1 7 6.666667
# 6 3 8 8.333333
这假设您的行和列已经按照正确的顺序排列。
如果您有更多数据帧,请将它们放入列表(see here for help with that)中,然后可以执行以下操作:
result = Reduce("+", list_of_data) / length(list_of_data)
如果您需要mean
的高级功能,例如忽略NA
或修整,则将无法使用。相反,我建议您使用将您的数据帧转换为矩阵,将它们堆叠为3-d数组,然后apply
添加mean
。
library(abind)
stack = abind(DG, DF, DT, along = 3)
# if you have data frames in a list, do this instead:
# stack = do.call(abind, c(list_of_data, along = 3))
apply(stack, MARGIN = 1:2, FUN = mean, na.rm = TRUE)
# y v x
# [1,] 1 3 6.666667
# [2,] 3 4 8.333333
# [3,] 1 5 6.666667
# [4,] 3 6 8.333333
# [5,] 1 7 6.666667
# [6,] 3 8 8.333333
我推荐的最后一种方法是“整洁”的方法-将您的数据合并到一个数据帧中,并使用分组操作生成结果。使用data.table
或dplyr
可以轻松完成此操作。有关更好的data.table
实现,请参见Uwe的答案。
library(dplyr)
bind_rows(list(DG, DF, DT), .id = ".id") %>%
group_by(.id) %>%
mutate(rn = row_number()) %>%
ungroup() %>%
select(-.id) %>%
group_by(rn) %>%
summarize_all(mean, na.rm = TRUE) %>%
select(-rn)
# # A tibble: 6 x 3
# y v x
# <dbl> <dbl> <dbl>
# 1 1 3 6.67
# 2 3 4 8.33
# 3 1 5 6.67
# 4 3 6 8.33
# 5 1 7 6.67
# 6 3 8 8.33