条件计算平均值

10

我希望对数据框的每个因子计算均值,但仅在满足特定条件时。例如,我有这个数据框:

> df <- data.frame(name = rep(c("A", "B", "C"), 20), 
                 variable1 = rep(c(1, 1, 1, 1, 1, NA), 10), 
                 variable2 = rep(c(2, NA, 2, 2, 2, 2), 10), 
                 variable3 = rep(c(NA, 3, 3, 3, 3, 3), 10))

> table(df$name, df$variable1)

     1
  A 20
  B 20
  C 10

> table(df$name, df$variable2)

     2
  A 20
  B 10
  C 20

> table(df$name, df$variable3)

     3
  A 10
  B 20
  C 20

我可以通过以下方式使用 dplyr 轻松地计算每个变量的平均值:

means <- df %>%
  group_by(name) %>%
  summarise_each(funs(mean(., na.rm = TRUE)))
> means
Source: local data frame [3 x 4]

  name variable1 variable2 variable3
1    A         1         2         3
2    B         1         2         3
3    C         1         2         3

然而,我的要求是仅在有11个或更多的观测值时计算平均值,否则在相应单元格中放置NA。换句话说,结果应该像这样:

  name variable1 variable2 variable3
1    A         1         2        NA
2    B         1        NA         3
3    C        NA         2         3
2个回答

6
我们可以创建一个名为f1的函数,如果非NA值的数量大于11 (sum(!is.na(x))>11),则进行平均计算,否则返回NA. 我们使用NA_real_作为默认值,因为默认的NA是逻辑类型,有些包会出现类冲突。
使用dplyr,我们按name进行分组,并在summarise_each中使用f1函数。
f1 <- function(x) if(sum(!is.na(x))>11) mean (x, na.rm=TRUE) else NA_real_
library(dplyr) 
df  %>% 
     group_by(name) %>%
     summarise_each(funs(f1))

使用类似的方法,可以使用data.table来将data.frame转换为data.tablesetDT(df))。我们通过列进行循环处理(lapply(.SD, ..)),并且按照name分组使用相同的函数。

library(data.table)
setDT(df)[,  lapply(.SD, f1), by = name]
#   name variable1 variable2 variable3
#1:    A         1         2        NA
#2:    B         1        NA         3
#3:    C        NA         2         3

太快了!非常感谢。在dplyr中有没有做同样的方法?这不是严格的条件,只是出于好奇。 - Mikhail Balyasin
@DavidArenburg 谢谢,我正在更新这个函数。 - akrun
1
@MikhailBalyasin,你觉得dplyr的语法更直观吗? - David Arenburg
3
@DavidArenburg,是的,因为我从未使用过data.table,但确实有一些使用dplyr的经验。 - Mikhail Balyasin

2
一种将数据从宽格式转换为长格式的替代方法。
library(reshape2)
df1 <- melt(df, id.vars = c("name")) # From wide to long
df1 <- df1 %>% group_by(name, variable) %>% 
       filter(n()>10) %>%
       summarize(mean = mean(value))

长格式输出:

   name  variable mean
1    A variable1    1
2    A variable2    2
3    A variable3   NA
4    B variable1    1
5    B variable2   NA
6    B variable3    3
7    C variable1   NA
8    C variable2    2
9    C variable3    3

宽幅输出:

dcast(df1,  name ~ variable, value.var = "mean")

  name variable1 variable2 variable3
1    A         1         2        NA
2    B         1        NA         3
3    C        NA         2         3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接