摘要
提供了一个数据框,其中我有几个作为变量的列(每个列都是数字但是一个,这是一个因素),行是观察,我想创建一个新列,其中包含所有数字列的平均值+另一个具有所有数字列的加权平均值。
我发现很多方法显然可以解决这个问题(使用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
我想创建
mean
的列,它是所有数值的平均值(除了neighbour
之外的所有列)和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个观察结果)
apply
创建了几列的平均值(这与我正在寻找的内容相近!)但仍然不知道如何排除neighbour
列,否则它将失败,B)计算加权平均值。任何人都可以为我带来一些亮点吗?我现在正在努力解决这个问题,我无法看到答案。
编辑:根据@ boshek的answer我试图从宽格式转换为长格式,然后应用summarise_each,但都没有成功:df = df %>%
gather(variable, value, -neighbour) %>%
group_by(neighbour, variable) %>%
summarise_each(., funs=mean)
答案 0 :(得分:3)
好的 - 所以你想要意味着ACROSS行吗?
我使用gather
中的dplyr
,然后将其与原始数据合并:
df.mean <- df %>%
gather(variable, value, -neighbour) %>%
group_by(neighbour) %>%
summarise(mean_value=mean(value), wmean_value=weighted.mean(value))
df.comb <- df %>%
full_join(.,df.mean, by=c("neighbour"))
有几种方法可以给这只猫上皮,但这只是一种。
这是你想要的吗?
答案 1 :(得分:1)
import pandas as pd
df = pd.DataFrame(range(1, 10))
df.plot(style="o")
答案 2 :(得分:1)
我认为base
中的rowMeans()函数可能是您最好的选择。
df$mean <- rowMeans(dplyr::select(df, starts_with("X")))
加权平均值可能更难。我无法找到一种快速而干净的方法来做到这一点,但这是一个有效的选择:
# define a function that calculates a weighted mean
wmean <- function(x, weight){
stopifnot(length(x) == length(weight))
if(sum(weight) != 1) {
message("Rescaling weights to sum to 1")
weight <- weight/sum(weight)
}
wx <- sum(x * weight)
return(wx)
}
# apply that function row by row to the X columns in df
df$wmean <- apply(X=dplyr::select(df, starts_with("X")), MARGIN=1, FUN=wmean, weight = weight)
答案 3 :(得分:0)
我知道我发布这个有点晚了,但我一直在寻找类似问题的解决方案,并从 rowWeightedMeans
库中找到了 matrixStats
,它也支持 na.rm
,你只需要转换成矩阵,它的工作原理如下:
library(matrixStats)
df$wmean <- rowWeightedMeans(as.matrix(df[ , c('X1', 'X2', 'X3', 'X4', 'X5')]), w = weight)
这对我来说非常有效,正如前面提到的,有额外的支持na.rm = TRUE
,我需要