【发布时间】:2014-06-04 20:45:31
【问题描述】:
我希望能够summarize 分组数据框,我并不总是知道会出现哪些变量,但我知道如果每个变量存在,我想如何总结它。
假设我有一个这样的数据框:
df <- data.frame(id = c(rep('a', 5), rep('b', 8), rep('c', 4)),
var1 = round(runif(17) * 10, 3),
var2 = sample(c(1:4), 17, replace = TRUE),
var4 = sample(1:1000, 17))
> df
id var1 var2 var4
1 a 5.930 4 360
2 a 7.265 2 713
3 a 3.704 3 117
4 a 5.149 2 782
5 a 3.777 2 640
6 b 4.183 2 802
7 b 0.107 2 638
8 b 5.323 4 327
9 b 4.322 2 631
10 b 0.937 3 921
11 b 5.558 2 570
12 b 5.902 4 363
13 b 0.671 3 432
14 c 0.475 1 845
15 c 1.562 3 620
16 c 4.464 2 997
17 c 1.714 2 714
注意 var3 丢失。有时它在那里,有时它不在。它存在时总是相同的类型。我希望能够巧妙地处理这两种情况。
假设,通过id 总结,我想得到var1 的平均值、var2 的中值、var3 的中值(如果存在)和var4 的最大值。如果所有变量都存在,我可以这样设置:
library('dplyr')
set.seed(111)
result <- df %>% group_by(id) %>%
summarize(var1 = mean(var1),
var2 = median(var2),
var3 = median(var3),
var4 = max(var4))
但是,由于var3 不存在,我收到一个错误:Error in median(var3) : object 'var3' not found。
直觉上,我会尝试类似:
result <- df %>% group_by(id) %>%
summarize(if('var1' %in% names(df)) var1 = mean(var1) else NULL,
if('var2' %in% names(df)) var2 = median(var2) else NULL,
if('var3' %in% names(df)) var3 = median(var3) else NULL,
if('var4' %in% names(df)) var4 = max(var4) else NULL)
但显然这不起作用,或者我的直觉有点不对劲。
有人对我如何使用 dplyr 干净利落地完成此任务有任何建议吗?正如您可能猜到的那样,df 实际上是一个包含许多列的大型数据框,var3 是可能丢失的任意列之一。
【问题讨论】:
-
如果是我,我可能会预先修改数据框以包含我可能拥有的最大列集,并且其中一些列可能全是 NA。
-
我认为你可以用一些有条件的
eval和parse来破解一些东西,但joran 的提议似乎更可行。 -
我的第一种方法可能是融合数据,然后使用 dplyr 获取每个组可能需要的所有统计信息,然后重新转换,然后您可以在进一步处理之前检查您实际拥有的列
-
@joran,我喜欢你的解决方案。我最终选择了@beginneR 的解决方案——可能会在所有
ifelses 上进行一些额外的输入,但我只需要一次列出所有变量。它最终看起来更整洁,更容易维护(我可以在一个地方添加/减去列的摘要)。