【发布时间】:2016-12-12 18:20:06
【问题描述】:
总结
提供了一个数据框,其中我有几列是变量(每个列都是数字,但一个是一个因素),行是观察值,我想创建一个新列,其中包含所有数字列的平均值 +另一个具有所有数字列的加权平均值。
我找到了一些明显解决这个问题的方法(使用dplyr、lapply、data.table...),但它们都不适用于宽数据帧(我不确定我是否可以将其转换为长格式 - 见下文,在标记为重复之前请耐心等待,因为我没有找到任何问题的答案)。
加长版:
我有一个宽格式的数据框,如下面提供的数据框(原始数据框有 1700 多个观测值,对 20 个变量分组到 30 个邻域),这是计算每个变量值的中位数的结果:
df = data.frame(matrix(rnorm(15), nrow = 3))
df$neighbour = c("neighbour1", "neighbour2", "neighbour3")
df
> df
X1 X2 X3 X4 X5 neighbour
1 1.0384405 0.6116994 -0.2075835 0.3206011 1.3855455 neighbour1
2 -0.5115649 -0.7722500 0.8374265 -1.3697758 0.1690452 neighbour2
3 1.0145282 0.6809156 -0.2918737 0.2912297 1.0689213 neighbour3
我想创作
- 1) 名为
mean的列是所有数值的平均值(除neighbour之外的所有列)和 - 2)
wmean列是每列的加权平均值,其中权重由以下向量提供:weight = c(.25, .05, .3, .3, .3)
我的第一次尝试是使用dplyr::mutate 创建这些列,但我没有成功,很可能是因为我做错了(所以如果我没有以常规平均值成功,我不知道如何执行加权平均):
df = df %>%
mutate(mean = mean(select(-neighbour)))
Error in mutate_impl(.data, dots) :
argumento no válido para un operador unitario
> df = df %>%
+ mutate(mean = mean())
Error in mutate_impl(.data, dots) :
el argumento "x" está ausente, sin valor por omisión
> df = df %>%
+ mutate(mean = mean(is.numeric()))
Error in mutate_impl(.data, dots) :
0 arguments passed to 'is.numeric' which requires 1
>
也尝试使用mutate_each,但我假设我的问题是我不知道如何传递正确的列来计算平均值(更不用说我不知道加权平均值)。
根据我的阅读,有很多方法可以创建所需的列:
This answer by Carlos Cinelli 给出了使用
sapply + filter、dplyr和tydr的示例,但所有这些解决方案都是基于它们不创建新列的事实,每个邻居的观察值的中位数,但每个变量值的中位数。This answer by @Roland 建议使用 data.table,但为了能够使用它,我的数据框应该有一个带有权重的列(而我没有它,恐怕我不会不知道如何创建这样的列,前提是我有超过 1700 次观察)
-
This answer by @Bob 使用
apply创建多列的平均值(这与我正在寻找的内容接近!)但仍然不知道如何 A)排除neighbour列,否则它将失败,并且 B ) 来计算加权平均值。
谁能给我带来一些光明?我现在非常忙于解决这个问题,以至于我看不到答案。
编辑:根据@boshek 的answer,我尝试将宽格式转换为长格式,然后应用 summarise_each,但都没有成功:
df = df %>%
gather(variable, value, -neighbour) %>%
group_by(neighbour, variable) %>%
summarise_each(., funs=mean)
【问题讨论】:
-
通常最好在制作随机数据示例之前使用
set.seed,这样更容易验证答案是否有效。出于同样的原因,我会使用sample(100, n)而不是rnorm(n),只是为了便于阅读。 -
在下面做了一些更改
-
仅供参考,Roland 的方式不需要权重栏。只需使用您的权重向量就可以了...
melt(data.table(df))[, .(mean(value), weighted.mean(value, weight)), by=neighbour, verbose=TRUE].. 然后您只需要合并/分配这些值。 -
感谢您的建议,弗兰克。我从未使用过
set.seed或sample(),我将不得不研究它们如何解决未来的问题。