使用mutate_at重新编码多个列值,并基于管道中的变异列创建新列

时间:2018-07-23 09:06:18

标签: r dplyr

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

我个人分别知道如何重新编码列中的值以及如何基于其他列中的值创建新列。但是,尝试在单个管道中同时执行这两个操作时遇到了问题。

我的数据如下:

df <- data.frame(Q1 = c(1, 2, 1, 4), Q2 = c(4, 2, 3, 1), Q3 = c(3, 3, 2, 3),
             Q4 = c(4, 4, 2, 4), Q5 = c(4, 2, 3, 1), Q6 = c(7, 2, 3, 1))

以我的样本数据集为例,我打算从Q1,Q2和Q3列中减去1,然后用新的(减去的)值替换原始值。同时,我想创建一个包含Q1,Q2和Q3平均值的新列,而忽略任何NA值或3的值。

我尝试了以下代码,但是Q1,Q2和Q3列未使用减去的值进行更新。

library(dplyr)

df$mean <- df %>%
  select(Q1, Q2, Q3) %>%
  mutate_all(funs(. - 1)) %>%
  apply(1, function(x) {
    round(mean(x[!is.na(x) & x != 3]), digits = 2)
  })

我尝试在管道中依次使用mutate_atmutate。但是,最终结果将删除所有其他未选中的列。我仍然希望其他列位于最终数据集中:

df <- df %>%
  select(Q1, Q2, Q3) %>%
  mutate_all(funs(. - 1)) %>%
  mutate(mean = apply(., 1, function(x)
    round(mean(x[!is.na(x) & x != 3]), digits = 2)))

非常感谢!

2 个答案:

答案 0 :(得分:1)

我们可以定义要对其执行操作的变量的向量,然后在mutate_at中使用它进行减法。相对而言,我们可以将select嵌套在您已经拥有的apply中,如下所示:

subtract <- c("Q1", "Q2", "Q3")
df2 <- df %>%
  mutate_at(subtract, funs(. - 1)) %>%
  mutate(mean = apply(select(., one_of(subtract)), 1, function(x)
    round(mean(x[!is.na(x) & x != 3]), digits = 2)))

df2
#   Q1 Q2 Q3 Q4 Q5 Q6 mean
# 1  0  3  2  4  4  7 1.00
# 2  1  1  2  4  2  2 1.33
# 3  0  2  1  2  3  3 1.00
# 4  3  0  2  4  1  1 1.00

答案 1 :(得分:1)

一个选择是,我们select必填列,并从每个列中减去-1,然后从这些列中选取meanrowwise并添加新列。

library(tidyverse)

df %>%
  select(1:3) %>%
  mutate_all(funs(. - 1)) %>%
  rowwise() %>%
  do( (.) %>% as.data.frame %>% 
      mutate(mean = mean(.[. != 3], na.rm = TRUE)))

#    Q1    Q2    Q3  mean
#* <dbl> <dbl> <dbl> <dbl>
#1  0     3.00  2.00  1.00
#2  1.00  1.00  2.00  1.33
#3  0     2.00  1.00  1.00
#4  3.00  0     2.00  1.00

也可以写为

(df[1:3] - 1) %>%
    rowwise() %>%
    do( (.) %>% as.data.frame %>% 
    mutate(mean = mean(.[. != 3], na.rm = TRUE)))

或者为了完全避免进行do调用,我们可以创建一个函数来计算mean并将其应用rowwise

apply_fun <- function(x) {
  mean(x[x != 3], na.rm = TRUE)
}

(df[1:3] - 1) %>%
  rowwise() %>%
  mutate(mean = apply_fun(c(Q1, Q2, Q3)))

 #    Q1    Q2    Q3  mean
 #  <dbl> <dbl> <dbl> <dbl>
 #1  0     3.00  2.00  1.00
 #2  1.00  1.00  2.00  1.33
 #3  0     2.00  1.00  1.00
 #4  3.00  0     2.00  1.00