【问题标题】:Using dplyr::case_when to conditionally change the value of a factored vaiable使用 dplyr::case_when 有条件地更改因子变量的值
【发布时间】:2022-12-03 12:03:54
【问题描述】:

我有一个需要大量数据清理的数据集。我的一些变量已经是因素。我知道因式变量的某些值是不正确的;但是,该因素的水平是有效的。

是的,我可以将分解后的变量转换回字符,然后在完成数据清理后重新分解——但那样我就不会学到任何东西。

library(dplyr)
## Create minimal reproducible example
min_re <- tibble(i = seq(1:10), my_letters = factor(substring("statistics", 1:10, 1:10), levels = letters))
# A tibble: 10 x 2
       i my_letters
   <int> <fct>     
 1     1 s         
 2     2 t         
 3     3 a         
 4     4 t         
 5     5 i         
 6     6 s         
 7     7 t         
 8     8 i         
 9     9 c         
10    10 s  

statistics 中的第一个s 是错误的值。我想用x替换第一个s,即xtatistics 我的第一次尝试:

min_re2 <- min_re %>%
  mutate(
    my_letters = case_when(
      my_letters == "s" & i == 1 ~ "x",
      TRUE ~ my_letters
    )
  )

结果错误:

Error in `mutate()`:
! Problem while computing `my_letters = case_when(my_letters == "s" & i == 1 ~ "x", TRUE
  ~ my_letters)`.
Caused by error in `` names(message) <- `*vtmp*` ``:
! 'names' attribute [1] must be the same length as the vector [0]
Run `rlang::last_error()` to see where the error occurred.

然而,这有效:

min_re$my_letters[which(min_re$my_letters == "s" & min_re == 1)] <- "x"
min_re

# A tibble: 10 x 2
       i my_letters
   <int> <fct>     
 1     1 x         
 2     2 t         
 3     3 a         
 4     4 t         
 5     5 i         
 6     6 s         
 7     7 t         
 8     8 i         
 9     9 c         
10    10 s  

为什么基本 r 方法在更改因子变量的值而不是 dplyr::case_when 时起作用?是否存在基本 r 方法执行的 dplyr::case_when 不愿意/无法执行的强制(例如,字符到因子)?

是否有更优雅的 dplyr-ish 方式来更改已分解变量的值?认为数据清洗不一定是重新调平。有一些观察表明 s 应该保留为 s

如果引入新级别,这将如何影响case_whenforcatscase_when 玩得好吗?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    部分答案:

    (是的,切换回字符、完成数据清理、然后重构要容易得多。)

    case_when 中,将更改后的值(右侧)作为所有必要级别的一个因素。

    library(dplyr)
    
    min_re <- tibble(i = seq(1:10), my_letters = factor(substring("statistics", 1:10, 1:10), levels = letters))
    
    min_re2 <- min_re %>%
      mutate(
        my_letters = case_when(
          my_letters == "s" & i == 1 ~ factor("x", levels = letters),
          TRUE ~ my_letters
        )
      )
    
    
    > min_re2
    # A tibble: 10 x 2
           i my_letters
       <int> <fct>     
     1     1 x         
     2     2 t         
     3     3 a         
     4     4 t         
     5     5 i         
     6     6 s         
     7     7 t         
     8     8 i         
     9     9 c         
    10    10 s 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-28
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      • 1970-01-01
      相关资源
      最近更新 更多