我有一个宽格式的问卷数据框架,每一列代表一个问卷项目。
数据如下所示:
df <- data.frame(Q1 = c(1, 4, 2, 3, 1, 1, 4, 4, 1, 2),
Q2 = c(NA, 3, 1, 4, NA, NA, 3, 4, 1, 2),
Q3 = c(3, 4, 1, 2, 4, NA, NA, 1, 1, 2),
Q4 = c(NA, 4, 1, 1, 1, 3, NA, 2, 2, NA))
我想使用rowSums
函数对每行中不是“ 4”的值求和,并排除NA,并将结果除以非4和非NA列的数量(使用dplyr管道)。我不想替换基础数据框中的4;我想保持原样。
由于我不知道如何将结果除以非4和非NA列的数量,因此我仅尝试尝试问题的第一部分。我已经使用以下代码尝试了第一部分,但没有成功:
library(dplyr)
df <- df %>%
as.data.frame() %>%
mutate(sum = rowSums(.[. != 4, ], na.rm = TRUE))
在上面的屏幕截图中,“平均值”列是非4和非NA值的总和除以非4和非NA列的数量。
谢谢!
答案 0 :(得分:2)
如果我们要在dplyr
中严格执行此操作,则可以将rowwise
与do
一起使用,并为每行计算不为4的值之和,然后将其除以{{1 }}的值。
length
编辑-在发布答案后,现在我意识到我们可以实际使用library(dplyr)
df %>%
rowwise() %>%
do( (.) %>% as.data.frame %>%
mutate(mean = sum(.[. != 4], na.rm = TRUE)/length(.[.!=4 & !is.na(.)])))
# Q1 Q2 Q3 Q4 mean
# * <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 1.00 NA 3.00 NA 2.00
# 2 4.00 3.00 4.00 4.00 3.00
# 3 2.00 1.00 1.00 1.00 1.25
# 4 3.00 4.00 2.00 1.00 2.00
# 5 1.00 NA 4.00 1.00 1.00
# 6 1.00 NA NA 3.00 2.00
# 7 4.00 3.00 NA NA 3.00
# 8 4.00 4.00 1.00 2.00 1.50
# 9 1.00 1.00 1.00 2.00 1.25
#10 2.00 2.00 2.00 NA 2.00
mean
答案 1 :(得分:2)
sp_mean <- function(x) mean(x[!is.na(x) & x != 4])
df$mean <-
df %>%
apply(1, sp_mean)
df
Q1 Q2 Q3 Q4 mean
1 1 NA 3 NA 2.00
2 4 3 4 4 3.00
3 2 1 1 1 1.25
4 3 4 2 1 2.00
5 1 NA 4 1 1.00
6 1 NA NA 3 2.00
7 4 3 NA NA 3.00
8 4 4 1 2 1.50
9 1 1 1 2 1.25
10 2 2 2 NA 2.00
编辑1 -更加健壮:
df$mean <-
df %>%
select(matches("^Q\\d+")) %>%
apply(1, sp_mean)
matches("^Q\\d+")
匹配以Q1, Q2,..., Q199, Q200, ...
开头的列名
编辑2 - 将我的sp_mean()与Ronak的解决方案结合在一起(不需要do()吗?):
df %>%
rowwise() %>%
mutate(mean = sp_mean(c(Q1, Q2, Q3, Q4)))
答案 2 :(得分:2)
您可以使用基数R:
df$mean = rowMeans(`is.na<-`(df,df==4),T)#or rowMeans(replace(df,df==4,NA),T)
> df
Q1 Q2 Q3 Q4 mean
1 1 NA 3 NA 2.00
2 4 3 4 4 3.00
3 2 1 1 1 1.25
4 3 4 2 1 2.00
5 1 NA 4 1 1.00
6 1 NA NA 3 2.00
7 4 3 NA NA 3.00
8 4 4 1 2 1.50
9 1 1 1 2 1.25
10 2 2 2 NA 2.00