计算按因子水平分组的有限范围数值变量的均值

Compute means of limited range of numeric variable grouped by factor levels

我有一个数据框,其中包含一个数值变量 V1 和一个因子变量 Effect:

set.seed(123)
df <- data.frame(
  V1 = c(rnorm(100)),
  Effect = sample(LETTERS[1:4], 100, replace = T)
)

对于每个 Effect 级别,我想计算 V1 的那些值在第一和第三四分位数之间的均值。我知道如何计算所有因子水平的四分位数:

quants <- aggregate(V1 ~ Effect, data = df, quantile) 
quants
  Effect       V1.0%      V1.25%      V1.50%      V1.75%     V1.100%
1      A -2.30916888 -0.55815839 -0.02854676  0.55115731  1.53261063
2      B -1.96661716 -0.37066003  0.33178196  0.68864025  1.36860228
3      C -1.13813694 -0.42358228  0.01381897  0.92773709  2.16895597
4      D -1.02642090 -0.49385424 -0.22407620  0.72100821  2.18733299

但现在我正在努力研究如何使用 quants 中的信息一次性计算所有因子水平的相关均值。

到目前为止我已经试过了:

我已经转换 quants 以使其更易于访问:

quants <- as.data.frame.list(quants)

然后我使用了这个tapply语句:

tapply(df$V1, df$Effect, function(x)  mean(x[x >= quants_new$V1.25. & x <= quants_new$V1.75.]))

但是结果不正确,并且有警告:

           A            B            C            D 
 0.172908276  0.167233413  0.002957323 -0.108590409 
Warning messages:
1: In x >= quants_new$V1.25. :
  longer object length is not a multiple of shorter object length
2: In x <= quants_new$V1.75. :
  longer object length is not a multiple of shorter object length
3: In x >= quants_new$V1.25. :
  longer object length is not a multiple of shorter object length
4: In x <= quants_new$V1.75. :
  longer object length is not a multiple of shorter object length

如何固定 tapply 语句来计算所有因子水平限制在四分位数范围内的均值?也欢迎其他解决方案。

我没有检查数字是否正确,但是使用 data.table 包中的 data.table() 而不是 data.frame,应该可以满足我的需求之后...

dt1[V1 > quantile(V1, 0.25) & V1 < quantile(V1, 0.75), 
  mean(V1), keyby = Effect]

这是按 "Effect" 对您的数据进行分组,在这些组中取中间 50% 的值,并取这些值的平均值。


编辑,上面的代码在分组之前先取子集(抱歉,我的测试没有做到这一点)以获取每个组的分位数:

dt1[dcast(dt1[, .(unlist(lapply(.SD, quantile, c(0.25, 0.75))), qt = c("lo", "up")), by = Effect], ... ~ qt, value.var = "V1"), on = "Effect"][V1 >= lo & V1 <= up, mean(V1), keyby = Effect]

这提供了与 Ronak 的答案相同的值。它获取每个组的分位数,dcast 扩大它,将其加入原始 data.table,然后使用新变量 lo 和 up(下分位数和上分位数边界)进行子集化并取每组的平均值剩余的值。

我们可以在 aggregate 内部做到这一点:

aggregate(V1~Effect, df, function(x) 
         mean(x[x >= quantile(x, 0.25) & x <= quantile(x, 0.75)], na.rm = TRUE))

使用 dplyr 可能是:

library(dplyr)

df %>%
  group_by(Effect) %>%
  summarise(mean_val = mean(V1[between(V1, quantile(V1, 0.25), 
                              quantile(V1, 0.75))], na.rm = TRUE))