繁体   English   中英

根据 R 中一列的值拆分数据框

[英]Split dataframe based on value of one column in R

我需要根据其中一列的值拆分一个大的 tibble 对象。 在下面的示例中,我计算了C列的每个后续值之间的差异。 当差异超过某个值(此处为D > 2 )时,我需要将小标题拆分为小标题列表。

require(dplyr)
TT <- tibble(A = 1:20, B = 21:40, C = c(1:5, 8:11, 18:20, 23:30))
TT <- TT %>% 
  mutate(D = C - dplyr::lag(C),
         E = D > 2)
TT
# A tibble: 20 x 5
       A     B     C     D E    
   <int> <int> <int> <int> <lgl>
 1     1    21     1    NA NA   
 2     2    22     2     1 FALSE
 3     3    23     3     1 FALSE
 4     4    24     4     1 FALSE
 5     5    25     5     1 FALSE
 6     6    26     8     3 TRUE 
 7     7    27     9     1 FALSE
 8     8    28    10     1 FALSE
 9     9    29    11     1 FALSE
10    10    30    18     7 TRUE 
11    11    31    19     1 FALSE
12    12    32    20     1 FALSE
13    13    33    23     3 TRUE 
14    14    34    24     1 FALSE
15    15    35    25     1 FALSE
16    16    36    26     1 FALSE
17    17    37    27     1 FALSE
18    18    38    28     1 FALSE
19    19    39    29     1 FALSE
20    20    40    30     1 FALSE

输出应该是四个小标题的列表,如下所示:

# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     1    21     1
2     2    22     2
3     3    23     3
4     4    24     4
5     5    25     5

# A tibble: 4 x 3
      A     B     C
  <int> <int> <int>
1     6    26     8
2     7    27     9
3     8    28    10
4     9    29    11

# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1    10    30    18
2    11    31    19
3    12    32    20

# A tibble: 8 x 3
      A     B     C
  <int> <int> <int>
1    13    33    23
2    14    34    24
3    15    35    25
4    16    36    26
5    17    37    27
6    18    38    28
7    19    39    29
8    20    40    30

谢谢

我们可以使用cumsum创建一个分组列, select感兴趣的列并使用group_split将数据集拆分为数据集list

library(dplyr)
library(tidyr)
TT %>%
     mutate(grp = cumsum(replace_na(E, FALSE))) %>% 
     select(A:C, grp) %>%
     group_split(grp, .keep = FALSE)

-输出

[[1]]
# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     1    21     1
2     2    22     2
3     3    23     3
4     4    24     4
5     5    25     5

[[2]]
# A tibble: 4 x 3
      A     B     C
  <int> <int> <int>
1     6    26     8
2     7    27     9
3     8    28    10
4     9    29    11

[[3]]
# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1    10    30    18
2    11    31    19
3    12    32    20

[[4]]
# A tibble: 8 x 3
      A     B     C
  <int> <int> <int>
1    13    33    23
2    14    34    24
3    15    35    25
4    16    36    26
5    17    37    27
6    18    38    28
7    19    39    29
8    20    40    30

我们也可以这样做:

library(dplyr)
library(purrr)

TT %>% 
  mutate(D = C - dplyr::lag(C, default = 0),
         E = cumsum(+(D > 2))) %>%
  split(.$E) %>%
  map(~ .x %>%
        select(A:C))

$`0`
# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     1    21     1
2     2    22     2
3     3    23     3
4     4    24     4
5     5    25     5

$`1`
# A tibble: 4 x 3
      A     B     C
  <int> <int> <int>
1     6    26     8
2     7    27     9
3     8    28    10
4     9    29    11

$`2`
# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1    10    30    18
2    11    31    19
3    12    32    20

$`3`
# A tibble: 8 x 3
      A     B     C
  <int> <int> <int>
1    13    33    23
2    14    34    24
3    15    35    25
4    16    36    26
5    17    37    27
6    18    38    28
7    19    39    29
8    20    40    30

另一种方法是直接在 split 函数中使用计算差异:

split(TT, ~cumsum(c(1, diff(C)) > 1))
$`0`
# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     1    21     1
2     2    22     2
3     3    23     3
4     4    24     4
5     5    25     5

$`1`
# A tibble: 4 x 3
      A     B     C
  <int> <int> <int>
1     6    26     8
2     7    27     9
3     8    28    10
4     9    29    11

$`2`
# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1    10    30    18
2    11    31    19
3    12    32    20

$`3`
# A tibble: 8 x 3
      A     B     C
  <int> <int> <int>
1    13    33    23
2    14    34    24
3    15    35    25
4    16    36    26
5    17    37    27
6    18    38    28
7    19    39    29
8    20    40    30

另一种选择是使用索引在lapply()内对 TRUE 进行拆分,如下所示:

TT$E[is.na(TT$D)]<-FALSE #Set NA's to FALSE

#index vector of TRUEs, and length
Ts<-c(which(TT$E),length(TT$E)+1) 

#lappy with indexing on True
lapply(1:length(Ts), function(x){
  A_index <- max(1,Ts[x-1])
  B_index <- min(length(TT$E),Ts[x]-1)
  TT[A_index:B_index,1:3])      })

结果:

     [[1]]
# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     1    21     1
2     2    22     2
3     3    23     3
4     4    24     4
5     5    25     5

[[2]]
# A tibble: 4 x 3
      A     B     C
  <int> <int> <int>
1     6    26     8
2     7    27     9
3     8    28    10
4     9    29    11

[[3]]
# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1    10    30    18
2    11    31    19
3    12    32    20

[[4]]
# A tibble: 8 x 3
      A     B     C
  <int> <int> <int>
1    13    33    23
2    14    34    24
3    15    35    25
4    16    36    26
5    17    37    27
6    18    38    28
7    19    39    29
8    20    40    30

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM