【问题标题】:Recoding all variables based on conditions根据条件重新编码所有变量
【发布时间】:2019-12-29 17:51:53
【问题描述】:

我正在尝试将我的数据集中所有处于“同意/不同意”比例的变量重新编码为数值。我尝试过使用 mutate_all 和 case_when,但随后它会为 id 列和 var3(下面的数据)等变量返回 NA 值。这是我使用的代码:

newdat <- olddat %>% mutate_all(funs(case_when(. == "Strongly Disagree (1)" ~ 1,
                                               . == "Disagree (2)" ~ 2,
                                               . == "Neutral (3)" ~ 3,
                                               . == "Agree (4)" ~ 4,
                                               . == "Strongly Agree (5)" ~ 5)))

我想要发生的事情如下:

有数据

id     var1                      var2           var3      var4
 1     Strongly Disagree (1)     Agree (4)      5         Agree (4)
 2     Strongly Disagree (1)     Neutral (3)    6         Neutral (3)
 3     Disagree (2)              Neutral (3)    4         Strongly Agree (5)
 4     Strongly Disagree (1)     Agree (4)      9         Disagree (2)
 5     Neutral (3)               Agree (4)      2         Agree (4)

想要数据

id     var1   var2   var3   var4
 1     1      4      5      4
 2     1      3      6      3
 3     2      3      4      5
 4     1      4      9      2
 5     3      4      2      4

附: 试图寻找一个现有的答案,但我找不到一个!也许我措辞有误?

【问题讨论】:

    标签: r dplyr data-manipulation data-cleaning


    【解决方案1】:

    您可以简单地从每个单元格中提取数字代码,因为您已经将它放在括号中。无需recode。这是使用stringr::str_extract()的一种方式-

    have %>% 
      mutate_at(vars(starts_with("var")), ~as.integer(str_extract(x, "[0-9]")))
    

    【讨论】:

      【解决方案2】:

      您需要使用mutate_at 而不是mutate_all,因为您只想更改选定的列,因为默认情况下case_when 中不匹配的值将转换为NA

      library(dplyr)
      
      df %>% mutate_at(vars(var1, var2, var4), 
                           ~(case_when(. == "Strongly Disagree (1)" ~ 1,
                                       . == "Disagree (2)" ~ 2,
                                       . == "Neutral (3)" ~ 3,
                                       . == "Agree (4)" ~ 4,
                                       . == "Strongly Agree (5)" ~ 5)))
      
      #  id var1 var2 var3 var4
      #1  1    1    4    5    4
      #2  2    1    3    6    3
      #3  3    2    3    4    5
      #4  4    1    4    9    2
      #5  5    3    4    2    4
      

      由于有很多列可以做到这一点,我们可以先找出哪些列需要更改,然后使用mutate_at

      cols <- which(colSums(sapply(df, grepl, pattern =  "Agree|Disagree")) > 0)
      
      df %>%
          mutate_at(cols, ~case_when(. == "Strongly Disagree (1)" ~ 1,
                          . == "Disagree (2)" ~ 2,
                          . == "Neutral (3)" ~ 3,
                          . == "Agree (4)" ~ 4,
                          . == "Strongly Agree (5)" ~ 5))
      

      【讨论】:

      • 这个问题是我实际上有大约 100 个变量,有没有办法只对那些有同意/不同意规模的人这样做?超过 50 人使用此量表。
      【解决方案3】:

      这看起来有点难看,我相信有更简单的解决方案,但它应该可以工作:

      newdat <- as.data.frame(sapply(1:ncol(olddat), function(x){if(x %in% c(1,4)){return(olddat[x])}else{return(sapply(olddat[x], function(y){as.numeric(gsub("[()]","",strsplit(y, split = " ")[[1]][2]))}))}}))
      

      它的作用基本上是遍历每一列。如果它是第 1 列或第 4 列,则按原样返回该列。如果是其他任何一个:它使用strsplit() 分割空白处的每个单元格,然后使用后半部分,使用gsub() 删除括号并使用as.numeric() 将其转换为数字。

      编辑:

      如果您有很多列并且不想手动指定它们,您可以按列类过滤:

      newdat <- as.data.frame(sapply(1:ncol(olddat), function(x){if(class(x) == "integer"){return(olddat[x])}else{return(sapply(olddat[x], function(y){as.numeric(gsub("[()]","",strsplit(y, split = " ")[[1]][2]))}))}}))
      

      【讨论】:

        猜你喜欢
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-09
        • 1970-01-01
        • 2019-01-24
        相关资源
        最近更新 更多