在不修改基础数据帧的情况下,在dplyr管道中排除特定值的rowSum

时间:2018-07-18 08:47:00

标签: r dplyr rowsum

我有一个宽格式的问卷数据框架,每一列代表一个问卷项目。

数据如下所示:

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

所需的输出如下所示: rowSums excluding particular value

在上面的屏幕截图中,“平均值”列是非4和非NA值的总和除以非4和非NA列的数量。

谢谢!

3 个答案:

答案 0 :(得分:2)

如果我们要在dplyr中严格执行此操作,则可以将rowwisedo一起使用,并为每行计算不为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