【问题标题】:Moving data from right to left column in a tibble在 tibble 中将数据从右列移动到左列
【发布时间】:2018-12-17 23:23:05
【问题描述】:

我有一个关于诊断信息的小标题:

data <- tibble(
  id = c(1:10),
  diagnosis_1 = c("F32", "F431", "R58", "S32", "F11", NA, NA, "Y67", "F32", "Z032"),
  diagnosis_2 = c(NA, NA, NA, NA, NA, NA, "G35", NA, NA, NA),
  diagnosis_3 = c("F40", NA, "R67", "F431", NA, "F60", "S58", "R68", "F11", NA),
  diagnosis_4 = c(NA, NA, "F65", NA, "F19", NA, NA, "F32", NA, NA)
)

作为清理过程的一部分,我删除了所有不符合特定标准的诊断(即不以字母 F、G 或 Z 开头)。使用以下代码:

data$diagnosis_1[str_sub(data$diagnosis_1, 1,1) %in% c("R", "S", "Y")] <- NA
data$diagnosis_2[str_sub(data$diagnosis_2, 1,1) %in% c("R", "S", "Y")] <- NA
data$diagnosis_3[str_sub(data$diagnosis_3, 1,1) %in% c("R", "S", "Y")] <- NA
data$diagnosis_4[str_sub(data$diagnosis_4, 1,1) %in% c("R", "S", "Y")] <- NA

以这个 tibble 结尾:

我现在需要将数据向左移动以从左到右填充列(即如果 diagnostic_2、diagnostics_3 或 diagnostic_4 有数据,则 diagnostic_1 不为空)。我试过使用 ifelse(),因为它是矢量化的,但我似乎无法让它与几个嵌套的 ifelse() 一起使用。

ifelse(is.na(data$diagnosis_1), data$diagnosis_2, data$diagnosis_1))

非常感谢所有建议。

编辑:添加预期输出:

【问题讨论】:

    标签: r dplyr stringr


    【解决方案1】:

    使用 dplyrtidyr。从宽到长重塑,排除"^RSY"NA诊断,从长到宽重塑。

    library(dplyr)
    library(tidyr)
    
    gather(data, key = "k", value = "v", -id) %>% 
      filter(!(grepl("^[R|S|Y]", v) | is.na(v))) %>% 
      group_by(id) %>% 
      mutate(diagN = paste0("diagnosis_", row_number())) %>% 
      select(-k) %>% 
      spread(key = "diagN", value = "v") %>% 
      ungroup()
    
    # # A tibble: 10 x 3
    #       id diagnosis_1 diagnosis_2
    #    <int> <chr>       <chr>      
    #  1     1 F32         F40        
    #  2     2 F431        NA         
    #  3     3 F65         NA         
    #  4     4 F431        NA         
    #  5     5 F11         F19        
    #  6     6 F60         NA         
    #  7     7 G35         NA         
    #  8     8 F32         NA         
    #  9     9 F32         F11        
    # 10    10 Z032        NA  
    

    【讨论】:

      【解决方案2】:

      我们首先将replace 以“R”、“S”或“Y”开头的值转换为NA,然后将非 NA 值左移。

      data[-1] <- lapply(data[-1], function(x) replace(x, grepl("^[R|S|Y]", x), NA))  
      data[] <- t(apply(data, 1, function(x) `length<-`(na.omit(x), length(x))))
      
      data
      # A tibble: 10 x 5
      #     id diagnosis_1 diagnosis_2 diagnosis_3 diagnosis_4
      #   <chr> <chr>       <chr>       <chr>       <chr>      
      # 1 " 1"  F32         F40         NA          NA         
      # 2 " 2"  F431        NA          NA          NA         
      # 3 " 3"  F65         NA          NA          NA         
      # 4 " 4"  F431        NA          NA          NA         
      # 5 " 5"  F11         F19         NA          NA         
      # 6 " 6"  F60         NA          NA          NA         
      # 7 " 7"  G35         NA          NA          NA         
      # 8 " 8"  F32         NA          NA          NA         
      # 9 " 9"  F32         F11         NA          NA         
      #10  10   Z032        NA          NA          NA    
      

      将非 NA 值向左移动取自 David 对 here 的回答。您也可以尝试任何其他方法来转移同一问题的值。

      【讨论】:

        【解决方案3】:

        你可以试试tidyverse

        library(tidyverse)
        data %>% 
          mutate_at(vars(starts_with("diagnosis")), funs(ifelse(str_sub(., 1, 1) %in% c("R", "S", "Y"), NA, .))) %>% 
          gather(k,v, -id) %>% 
          group_by(id) %>% 
          arrange(id) %>% 
          mutate(v=ifelse(k == "diagnosis_1", v[!is.na(v)][1], v)) %>% 
          spread(k, v)
        # A tibble: 10 x 5
        # Groups:   id [10]
              id diagnosis_1 diagnosis_2 diagnosis_3 diagnosis_4
           <int> <chr>       <chr>       <chr>       <chr>      
         1     1 F32         NA          F40         NA         
         2     2 F431        NA          NA          NA         
         3     3 F65         NA          NA          F65        
         4     4 F431        NA          F431        NA         
         5     5 F11         NA          NA          F19        
         6     6 F60         NA          F60         NA         
         7     7 G35         G35         NA          NA         
         8     8 F32         NA          NA          F32        
         9     9 F32         NA          F11         NA         
        10    10 Z032        NA          NA          NA 
        

        由于不清楚 OP 想要什么(请参阅下面的讨论),您也可以尝试

        data %>% 
          mutate_at(vars(starts_with("diagnosis")), funs(ifelse(str_sub(., 1, 1) %in% c("R", "S", "Y"), NA, .))) %>% 
          gather(k,v, -id) %>% 
          group_by(id) %>% 
          arrange(id) %>% 
          mutate(v=c(v[!is.na(v)], rep(NA, length(v) - length(v[!is.na(v)])))) %>% 
          spread(k, v)
        # A tibble: 10 x 5
        # Groups:   id [10]
              id diagnosis_1 diagnosis_2 diagnosis_3 diagnosis_4
           <int> <chr>       <chr>       <chr>       <chr>      
         1     1 F32         F40         NA          NA         
         2     2 F431        NA          NA          NA         
         3     3 F65         NA          NA          NA         
         4     4 F431        NA          NA          NA         
         5     5 F11         F19         NA          NA         
         6     6 F60         NA          NA          NA         
         7     7 G35         NA          NA          NA         
         8     8 F32         NA          NA          NA         
         9     9 F32         F11         NA          NA         
        10    10 Z032        NA          NA          NA
        

        【讨论】:

        • @RonakShah 他应该包括可重现的输出。只要我们不知道他到底想要什么。 ;)
        • @RonakShah IMO 他只想更新diagnosis_1 并保留其他列?!
        • @RonakShah 也包含了该解决方案。
        【解决方案4】:

        您可以将Reduce 与来自dplyrcoalesce 一起使用,即

        df$diagnosis_1 <- Reduce(dplyr::coalesce, df[-1])
        
        #id diagnosis_1 diagnosis_2 diagnosis_3 diagnosis_4
        #   <int> <chr>       <chr>       <chr>       <chr>      
        # 1     1 F32         <NA>        F40         <NA>       
        # 2     2 F431        <NA>        <NA>        <NA>       
        # 3     3 F65         <NA>        <NA>        F65        
        # 4     4 F431        <NA>        F431        <NA>       
        # 5     5 F11         <NA>        <NA>        F19        
        # 6     6 F60         <NA>        F60         <NA>       
        # 7     7 G35         G35         <NA>        <NA>       
        # 8     8 F32         <NA>        <NA>        F32        
        # 9     9 F32         <NA>        F11         <NA>       
        #10    10 Z032        <NA>        <NA>        <NA> 
        

        【讨论】:

          【解决方案5】:

          以下解决方案使用包dedupewider中的函数na_move

          library(dedupewider)
          
          na_move(data) # 'right' direction is by default
          
          #> # A tibble: 10 x 5
          #>    id    diagnosis_1 diagnosis_2 diagnosis_3 diagnosis_4
          #>  * <chr> <chr>       <chr>       <lgl>       <lgl>      
          #>  1 1     F32         F40         NA          NA         
          #>  2 2     F431        <NA>        NA          NA         
          #>  3 3     F65         <NA>        NA          NA         
          #>  4 4     F431        <NA>        NA          NA         
          #>  5 5     F11         F19         NA          NA         
          #>  6 6     F60         <NA>        NA          NA         
          #>  7 7     G35         <NA>        NA          NA         
          #>  8 8     F32         <NA>        NA          NA         
          #>  9 9     F32         F11         NA          NA         
          #> 10 10    Z032        <NA>        NA          NA
          

          【讨论】:

            猜你喜欢
            • 2015-06-15
            • 1970-01-01
            • 2022-01-18
            • 1970-01-01
            • 1970-01-01
            • 2016-08-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多