【问题标题】:Combine several columns with NA values in R, but only use NA if none of the columns has data在 R 中将几列与 NA 值合并,但仅在没有列有数据时才使用 NA
【发布时间】:2017-05-11 19:25:41
【问题描述】:

如果您提出如何改进我的代码的建议,我将不胜感激。第二次尝试有效并提供了所需的输出,但我认为它非常乏味。也许有一个更简单的解决方案。

原始数据集包括 8 列,其中包含有关屏幕分辨率的信息。每列代表一组不同的问题,参与者被随机分配到其中,这意味着如果在该特定集合中没有提出解决问题,则插入 NA,尽管参与者可能在不同的集合中回答了它。

我对数据进行了匿名化和简化,只包含我提到的原始八列中的三列:

    ID  ResSet1 ResSet2 ResSet3
1   NA  NA  NA
2   NA  NA  NA
3   NA  NA  NA
4   NA  NA  NA
5   NA  1280x800    NA
6   NA  NA  NA
7   NA  NA  NA
8   NA  NA  NA
9   NA  1440x900    NA
10  NA  NA  1366x768
11  NA  NA  NA
12  NA  NA  NA
13  NA  NA  NA
14  NA  1366x768    NA
15  NA  NA  NA
16  NA  NA  1920x1080
17  NA  NA  NA
18  1600x1200   NA  NA
19  NA  NA  NA
20  NA  NA  1366x768
21  NA  NA  1440x900
22  NA  1680x1050   NA
23  1600x900    NA  NA
24  NA  NA  NA
25  NA  NA  1920x1080
26  NA  NA  NA
27  NA  1440x900    NA
28  NA  NA  NA
29  NA  NA  1600x900
30  1280x800    NA  NA

我的目标是将所有集合合并到一个名为 Resolutions 的列中;但是,仅当特定行在所有集合/列中都包含 NA 值时,才将其标记为 NA,如果一个集合包含分辨率,则仅应将分辨率值写入列。

我尝试了以下依赖 dplyr 和 tidyr 包,这是我的两次尝试。

第一次尝试使用 mutate 和 paste0:

x = test %>% mutate(Resolution = paste0(ResSet1, ResSet2, ResSet3))

结果如下:(原始数据集的输出)

    x$Resolution

1] "NANANANANANANA1366x768"  "NANA1440x900NANANANANA"  "NANANANANANA1344x840NA"  "NANANANA1366x768NANANA" 
      [5] "NA1280x800NANANANANANA"  "NANANANANANANA1366x768"  "NANANANA1366x768NANANA"  "NANANANANANA1536x864NA" 
      [9] "NA1440x900NANANANANANA"  "NANANA1366x768NANANANA"  "NANANANANANANA1280x800"  "NANANANANA1366x768NANA" 
     [13] "NANA1408x792NANANANANA"  "NA1366x768NANANANANANA"  "NANANANANA1920x1080NANA" "NANANA1920x1080NANANANA"

我不知道如何在使用 paste0 时执行类似 rm.na 函数的操作,所以在我第二次尝试使用 unite 时;我已将 NA 字符串替换为“”,然后将空单元格替换为正确的 NA。

x2 = test %>% unite(Resolution, ResSet1, ResSet2, ResSet3, 
                     remove = TRUE, sep = "") %>% 
  mutate(Resolution = str_replace_all(Resolution, "NA", "")) %>%
  mutate(Resolution = ifelse(Resolution == "", NA, Resolution))

结果如下:(原始数据集的输出)

x2$Resolution

"1366x768"  NA          "1280x800"  "1366x768"  "1366x768"  "1366x768"  NA          "1440x900"

这其实是我需要实现的;但是,该解决方案对我来说似乎不是很优雅,也许有一种更简单的方法。

感谢您的建议。

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    coalesce可以用来选择几个向量各自值的第一个非NA值:

    library(dplyr)
    
    df <- df %>% 
        mutate_at(vars(contains('ResSet')), as.character) %>%    # ensure all are character, not factor
        mutate(Resolutions = coalesce(ResSet1, ResSet2, ResSet3))    # coalesce
    
    tail(df)
    #>    ID  ResSet1  ResSet2   ResSet3 Resolutions
    #> 25 25     <NA>     <NA> 1920x1080   1920x1080
    #> 26 26     <NA>     <NA>      <NA>        <NA>
    #> 27 27     <NA> 1440x900      <NA>    1440x900
    #> 28 28     <NA>     <NA>      <NA>        <NA>
    #> 29 29     <NA>     <NA>  1600x900    1600x900
    #> 30 30 1280x800     <NA>      <NA>    1280x800
    

    【讨论】:

      【解决方案2】:

      您可以在基本 R 中轻松做到这一点 - 我假设第一列是 ID,所有其他列都是分辨率列:

      df$res <- df[cbind(seq_len(nrow(df)), max.col(!is.na(df[-1]))+1)]
      

      【讨论】:

        【解决方案3】:

        尝试以下方法:

        使用:

        df <- structure(list(ID = 1:30, ResSet1 = c(NA, NA, NA, NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "1600x1200", NA, 
        NA, NA, NA, "1600x900", NA, NA, NA, NA, NA, NA, "1280x800"), 
            ResSet2 = c(NA, NA, NA, NA, "1280x800", NA, NA, NA, "1440x900", 
            NA, NA, NA, NA, "1366x768", NA, NA, NA, NA, NA, NA, NA, "1680x1050", 
            NA, NA, NA, NA, "1440x900", NA, NA, NA), ResSet3 = c(NA, 
            NA, NA, NA, NA, NA, NA, NA, NA, "1366x768", NA, NA, NA, NA, 
            NA, "1920x1080", NA, NA, NA, "1366x768", "1440x900", NA, 
            NA, NA, "1920x1080", NA, NA, NA, "1600x900", NA)), .Names = c("ID", 
        "ResSet1", "ResSet2", "ResSet3"), class = "data.frame", row.names = c(NA, 
        -30L))
        

        然后:

        df$newcol <- 
          apply(df[,-1], 1, function(row) {
             if(all(is.na(row))) return(NA)
             else return(unique(row[!is.na(row)]))
          })
        

        给予:

        head(df)
          ID ResSet1  ResSet2 ResSet3   newcol
        1  1    <NA>     <NA>    <NA>     <NA>
        2  2    <NA>     <NA>    <NA>     <NA>
        3  3    <NA>     <NA>    <NA>     <NA>
        4  4    <NA>     <NA>    <NA>     <NA>
        5  5    <NA> 1280x800    <NA> 1280x800
        6  6    <NA>     <NA>    <NA>     <NA>
        

        这里使用unique 的动机是,即使您的示例数据中每行没有重复观察,但在您的实际数据中可能就是这种情况(据我了解您的问题描述)。如果不是这种情况,您可以省略unique。如果有两个不同的分辨率,您可能希望将其包装成例如list 或其他。

        【讨论】:

          【解决方案4】:

          您可以通过结合使用gatherright_join 来实现此目的。使用这种方法,您不必手动指定所有列,以防您的 data.frame 仅包含 ID 和其他八列。

          library(tidyverse)
          
          df %>% 
            gather(key, resolution, -ID) %>% 
            select(-key) %>% 
            na.omit() %>% 
            right_join(df)
          #> Joining, by = "ID"
          #>    ID resolution   ResSet1   ResSet2   ResSet3
          #> 1   1       <NA>      <NA>      <NA>      <NA>
          #> 2   2       <NA>      <NA>      <NA>      <NA>
          #> 3   3       <NA>      <NA>      <NA>      <NA>
          #> 4   4       <NA>      <NA>      <NA>      <NA>
          #> 5   5   1280x800      <NA>  1280x800      <NA>
          #> 6   6       <NA>      <NA>      <NA>      <NA>
          #> 7   7       <NA>      <NA>      <NA>      <NA>
          #> 8   8       <NA>      <NA>      <NA>      <NA>
          #> 9   9   1440x900      <NA>  1440x900      <NA>
          #> 10 10   1366x768      <NA>      <NA>  1366x768
          #> 11 11       <NA>      <NA>      <NA>      <NA>
          #> 12 12       <NA>      <NA>      <NA>      <NA>
          #> 13 13       <NA>      <NA>      <NA>      <NA>
          #> 14 14   1366x768      <NA>  1366x768      <NA>
          #> 15 15       <NA>      <NA>      <NA>      <NA>
          #> 16 16  1920x1080      <NA>      <NA> 1920x1080
          #> 17 17       <NA>      <NA>      <NA>      <NA>
          #> 18 18  1600x1200 1600x1200      <NA>      <NA>
          #> 19 19       <NA>      <NA>      <NA>      <NA>
          #> 20 20   1366x768      <NA>      <NA>  1366x768
          #> 21 21   1440x900      <NA>      <NA>  1440x900
          #> 22 22  1680x1050      <NA> 1680x1050      <NA>
          #> 23 23   1600x900  1600x900      <NA>      <NA>
          #> 24 24       <NA>      <NA>      <NA>      <NA>
          #> 25 25  1920x1080      <NA>      <NA> 1920x1080
          #> 26 26       <NA>      <NA>      <NA>      <NA>
          #> 27 27   1440x900      <NA>  1440x900      <NA>
          #> 28 28       <NA>      <NA>      <NA>      <NA>
          #> 29 29   1600x900      <NA>      <NA>  1600x900
          #> 30 30   1280x800  1280x800      <NA>      <NA>
          

          【讨论】:

            猜你喜欢
            • 2018-06-25
            • 1970-01-01
            • 2018-07-27
            • 1970-01-01
            • 2020-06-17
            • 1970-01-01
            • 1970-01-01
            • 2021-01-26
            • 1970-01-01
            相关资源
            最近更新 更多