【问题标题】:Calculate the mean (and weighted mean) of several columns within a dataframe计算数据框中几列的平均值(和加权平均值)
【发布时间】: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(),我将不得不研究它们如何解决未来的问题。

标签: r dataframe


【解决方案1】:
df$mean <- apply(df[1:5], 1, mean)
df$wt.mean <- apply(df[1:5], 1, weighted.mean, weight)

【讨论】:

  • 无需创建匿名函数,apply(df[1:5], 1, weighted.mean, weight) 也能正常工作
【解决方案2】:

好的 - 所以你想要的意思是跨行?

我会使用dplyr 中的gather,然后将其与您的原始数据合并:

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"))

有几种方法可以给这只猫剥皮,但这是其中之一。

这是你想要的吗?

【讨论】:

  • 恐怕它没有达到我想要的效果,因为它没有创建新列。
  • 尝试使用mutate_each 而不是summarise_each,然后确保将结果存储到对象中。
  • 做了一些修改。我认为它应该解决您的问题。
  • 谢谢,但恐怕我还没有让自己理解,因为 AFAIK mutate_each 在列的值内进行计算,这不是我想要实现的。相反,我想对每个邻居的观察求平均值 - 这是我想在每行的基础上进行计算。
  • 修改了解决方案。这是你想要的吗?如果没有,您可以发布一个您所追求的示例吗?
【解决方案3】:

我认为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)

【讨论】:

    【解决方案4】:

    我知道我发布这个有点晚了,但我正在寻找类似问题的解决方案,并从matrixStats 库中找到了rowWeightedMeans,它也支持na.rm,你只需要转换到矩阵,它的工作原理如下:

    library(matrixStats)
    df$wmean <- rowWeightedMeans(as.matrix(df[ , c('X1', 'X2', 'X3', 'X4', 'X5')]), w = weight)
    

    这对我来说非常有效,并且如上所述,具有支持 na.rm = TRUE 的额外功能,这是我需要的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 2020-12-07
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多