R_splitting 基于列式 NA 值出现的数据框

R_splitting a data frame based on column-wise NA value occurance

示例数据

set.seed(16)
aaa <- 1:1000
aaa[round(runif(100,1,1000))] <- NA
aaa.df <- as.data.frame(matrix(aaa, ncol=5))

我希望根据哪些列包含 NA 值将 aaa.df 分成多个组,例如,如果第 10、16、200 行在同一行中具有 NA 值列,我希望这些行属于一组,依此类推。它也应该工作时。 a 和 b 中没有 NA 值。连续有多个 NA 值。

我也想分组的时候保留原来的行号

编辑:为了更清楚,这是预期的输出(使用 Taufi 的答案获得,但我仍在寻找更优雅的方式)

[[1]]
# A tibble: 119 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1     1   201   401   601   801     1
 2     2   202   402   602   802     2
 3     3   203   403   603   803     3
 4     4   204   404   604   804     4
 5     5   205   405   605   805     5
 6     6   206   406   606   806     6
 7     7   207   407   607   807     7
 8     8   208   408   608   808     8
 9     9   209   409   609   809     9
10    10   210   410   610   810    10
# ... with 109 more rows

[[2]]
# A tibble: 14 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1    20   220   420   620    NA    20
 2    32   232   432   632    NA    32
 3    47   247   447   647    NA    47
 4    70   270   470   670    NA    70
 5    85   285   485   685    NA    85
 6    92   292   492   692    NA    92
 7   129   329   529   729    NA   129
 8   132   332   532   732    NA   132
 9   137   337   537   737    NA   137
10   151   351   551   751    NA   151
11   152   352   552   752    NA   152
12   168   368   568   768    NA   168
13   178   378   578   778    NA   178
14   181   381   581   781    NA   181

[[3]]
# A tibble: 15 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1    11   211   411    NA   811    11
 2    37   237   437    NA   837    37
 3    62   262   462    NA   862    62
 4    82   282   482    NA   882    82
 5    83   283   483    NA   883    83
 6    89   289   489    NA   889    89
 7   107   307   507    NA   907   107
 8   115   315   515    NA   915   115
 9   116   316   516    NA   916   116
10   117   317   517    NA   917   117
11   118   318   518    NA   918   118
12   165   365   565    NA   965   165
13   176   376   576    NA   976   176
14   189   389   589    NA   989   189
15   200   400   600    NA  1000   200

[[4]]
# A tibble: 1 x 6
   V1.y  V2.y  V3.y  V4.y  V5.y    V6
  <int> <int> <int> <int> <int> <int>
1    12   212   412    NA    NA    12

[[5]]
# A tibble: 16 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1    17   217    NA   617   817    17
 2    28   228    NA   628   828    28
 3    31   231    NA   631   831    31
 4    48   248    NA   648   848    48
 5    58   258    NA   658   858    58
 6    72   272    NA   672   872    72
 7    80   280    NA   680   880    80
 8   126   326    NA   726   926   126
 9   144   344    NA   744   944   144
10   145   345    NA   745   945   145
11   149   349    NA   749   949   149
12   153   353    NA   753   953   153
13   186   386    NA   786   986   186
14   190   390    NA   790   990   190
15   192   392    NA   792   992   192
16   196   396    NA   796   996   196
and so on..

一个快速但不是很优雅的解决方案如下。注意后面原来的行号在V6.

aaa.df %<>% mutate(Rownum = 1:nrow(aaa.df))
Aux.df <- cbind(is.na(aaa.df[, 1:(ncol(aaa.df) - 1)]), 1:nrow(aaa.df)) %>% 
                    as.data.frame %>% 
                            group_by(V1, V2, V3, V4, V5) %>%  
                                          group_split
Sol <- lapply(Aux.df, function(x) inner_join(x, aaa.df, by = c("V6"="Rownum")) %>%
                                 select(V1.y, V2.y, V3.y, V4.y, V5.y, V6)) 

输出

    > Sol
[[1]]
# A tibble: 119 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1     1   201   401   601   801     1
 2     2   202   402   602   802     2
 3     3   203   403   603   803     3
 4     4   204   404   604   804     4
 5     5   205   405   605   805     5
 6     6   206   406   606   806     6
 7     7   207   407   607   807     7
 8     8   208   408   608   808     8
 9     9   209   409   609   809     9
10    10   210   410   610   810    10
# ... with 109 more rows

[[2]]
# A tibble: 14 x 6
    V1.y  V2.y  V3.y  V4.y  V5.y    V6
   <int> <int> <int> <int> <int> <int>
 1    20   220   420   620    NA    20
 2    32   232   432   632    NA    32
 3    47   247   447   647    NA    47
 4    70   270   470   670    NA    70
 5    85   285   485   685    NA    85
 6    92   292   492   692    NA    92
 7   129   329   529   729    NA   129
 8   132   332   532   732    NA   132
 9   137   337   537   737    NA   137
10   151   351   551   751    NA   151
11   152   352   552   752    NA   152
12   168   368   568   768    NA   168
13   178   378   578   778    NA   178
14   181   381   581   781    NA   181
....

等等...

除了我之前更蛮力的答案之外,我想出了以下更优雅的单行方式,避免了任何不必要的连接或中间分配步骤。既然你已经接受了我之前的回答,我就让它保持原样,并在下面添加概念上不同的一行。这个想法是 split() data.frame 基于 which() 中的 pasted 列编号,表明存在 NA.

split(aaa.df, 
           apply(aaa.df, 1, 
                            function(x) paste(which(is.na(x)), collapse = ",")))

输出

$`1`
    V1  V2  V3  V4  V5
77  NA 277 477 677 877
93  NA 293 493 693 893
97  NA 297 497 697 897
109 NA 309 509 709 909
119 NA 319 519 719 919
140 NA 340 540 740 940
154 NA 354 554 754 954
158 NA 358 558 758 958
171 NA 371 571 771 971
172 NA 372 572 772 972

$`1,2,3`
   V1 V2 V3  V4  V5
51 NA NA NA 651 851

$`1,3,5`
   V1  V2 V3  V4 V5
75 NA 275 NA 675 NA

$`1,4`
    V1  V2  V3 V4  V5
194 NA 394 594 NA 994

$`1,4,5`
   V1  V2  V3 V4 V5
49 NA 249 449 NA NA
 ... 

等等...