均值的条件计算
Conditional calculation of mean
我想为每个因素计算数据框的均值,但前提是满足特定条件。例如,我有这个数据框:
> 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
我们可以创建一个函数 (f1
),它将计算 if
非 NA
值的数量大于 11 (sum(!is.na(x))>11
) 或否则我们得到 NA
。我使用 NA_real_
作为默认值 NA
是合乎逻辑的 class 并且在某些包中可能存在 class 的冲突。
使用 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.table
(setDT(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
将先前的数据从宽数据转换为长数据的替代方法。
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
我想为每个因素计算数据框的均值,但前提是满足特定条件。例如,我有这个数据框:
> 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
我们可以创建一个函数 (f1
),它将计算 if
非 NA
值的数量大于 11 (sum(!is.na(x))>11
) 或否则我们得到 NA
。我使用 NA_real_
作为默认值 NA
是合乎逻辑的 class 并且在某些包中可能存在 class 的冲突。
使用 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.table
(setDT(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
将先前的数据从宽数据转换为长数据的替代方法。
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