平均多个数据帧中的行和列单元

时间:2019-01-18 16:11:11

标签: r

我有多个数据框,例如:

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))'
    ....

实际上,yvx是不同的位置,并且是1-6个时间步长。我想平均每个时间步长和位置的数据。最终,我需要一个数据集,看起来像示例数据集之一,但每个单元格中都有平均值。

我有一个带有循环的有效示例,但是对于大型数据集,它非常慢,因此我尝试了套用apply和rowSums的各种组合,但都没有解决。

2 个答案:

答案 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.tabledplyr可以轻松完成此操作。有关更好的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