用R中的tidyverse按组完成整数序列

用R中的tidyverse按组完成整数序列,r,dplyr,tidyverse,tidyr,R,Dplyr,Tidyverse,Tidyr,给定一个数据集,其中包含一个分组变量和一列不完整的整数(包含NAs),开始和结束整数因组而异,每个组的长度也不同(可能是NA)。如何通过完成序列来填充NA整数值 以下数据集可用作示例: library(dplyr) set.seed(5112021) dat1 <- bind_rows(data.frame(Group=1,Seq=(3:20)), data.frame(Group=2,Seq=(-1:25))) %>% mutate(rn =

给定一个数据集,其中包含一个分组变量和一列不完整的整数(包含NAs),开始和结束整数因组而异,每个组的长度也不同(可能是NA)。如何通过完成序列来填充NA整数值

以下数据集可用作示例:

library(dplyr)
set.seed(5112021)
dat1 <- bind_rows(data.frame(Group=1,Seq=(3:20)),
                  data.frame(Group=2,Seq=(-1:25))) %>%
  mutate(rn = rnorm(45,mean=0.5,sd=1),
         Seq = ifelse(rn < 0.4,NA,Seq)) %>% 
  select(-rn) %>% 
  group_by(Group) %>% 
  mutate(Seq = ifelse(Seq==-1,NA,Seq))

dat1
   Group Seq
1      1  NA
2      1  NA
3      1  NA
4      1   6
5      1   7
6      1   8
7      1  NA
8      1  10
9      1  11
10     1  NA
11     1  13
12     1  NA
13     1  15
14     1  NA
15     1  NA
16     1  NA
17     1  NA
18     1  20
19     2  NA
20     2   0
21     2  NA
22     2   2
23     2   3
24     2  NA
25     2   5
26     2   6
27     2   7
28     2   8
29     2  NA
30     2  10
31     2  NA
32     2  12
33     2  NA
34     2  NA
35     2  NA
36     2  16
37     2  17
38     2  NA
39     2  NA
40     2  NA
41     2  NA
42     2  22
43     2  NA
44     2  NA
45     2  NA
库(dplyr)
种子集(5112021)
dat1%
突变(rn=rnorm(45,平均值=0.5,标准差=1),
Seq=ifelse(rn<0.4,NA,Seq))%>%
选择(-rn)%>%
分组依据(分组)%>%
突变(Seq=ifelse(Seq==-1,NA,Seq))
dat1
分组顺序
11NA
21 NA
31 NA
4      1   6
5      1   7
6      1   8
71NA
8      1  10
9      1  11
101NA
11     1  13
12 1 NA
13     1  15
14 1 NA
15 1 NA
16.1 NA
17 1 NA
18     1  20
19 2 NA
20     2   0
21 2 NA
22     2   2
23     2   3
24.2 NA
25     2   5
26     2   6
27     2   7
28     2   8
29 2 NA
30     2  10
31 2 NA
32     2  12
33 2 NA
34 2 NA
35 2 NA
36     2  16
37     2  17
38 2 NA
39 2 NA
40 2 NA
41 2 NA
42     2  22
43 2 NA
44 2 NA
45 2 NA
实现这一点的一种方法是按组使用行数(因为它们是一个整数序列),计算非缺失值和行号(唯一值)之间的差值,然后将该值加回到行号

比如说

dat2 <- dat1 %>% 
  group_by(Group) %>% 
  mutate(rn = row_number(),
         diff = mean(Seq-rn,na.rm=T)) %>% 
  mutate(New_Seq = rn+diff) %>% 
  select(-rn,-diff)

dat2
   Group Seq New_Seq
1      1  NA       3
2      1  NA       4
3      1  NA       5
4      1   6       6
5      1   7       7
6      1   8       8
7      1  NA       9
8      1  10      10
9      1  11      11
10     1  NA      12
11     1  13      13
12     1  NA      14
13     1  15      15
14     1  NA      16
15     1  NA      17
16     1  NA      18
17     1  NA      19
18     1  20      20
19     2  NA      -1
20     2   0       0
21     2  NA       1
22     2   2       2
23     2   3       3
24     2  NA       4
25     2   5       5
26     2   6       6
27     2   7       7
28     2   8       8
29     2  NA       9
30     2  10      10
31     2  NA      11
32     2  12      12
33     2  NA      13
34     2  NA      14
35     2  NA      15
36     2  16      16
37     2  17      17
38     2  NA      18
39     2  NA      19
40     2  NA      20
41     2  NA      21
42     2  22      22
43     2  NA      23
44     2  NA      24
45     2  NA      25
dat2%
分组依据(分组)%>%
变异(rn=行数(),
差异=平均值(序号rn,na.rm=T))%>%
变异(新序列=rn+diff)%>%
选择(-rn,-diff)
dat2
集团序号新
1 NA 3
2 1 NA 4
3 1 NA 5
4      1   6       6
5      1   7       7
6      1   8       8
7 1 NA 9
8      1  10      10
9      1  11      11
10 1 NA 12
11     1  13      13
12 1 NA 14
13     1  15      15
14 1 NA 16
15 1 NA 17
16 1 NA 18
17 1 NA 19
18     1  20      20
19 2 NA-1
20     2   0       0
21 2 NA 1
22     2   2       2
23     2   3       3
24 2 NA 4
25     2   5       5
26     2   6       6
27     2   7       7
28     2   8       8
29 2 NA 9
30     2  10      10
31 2 NA 11
32     2  12      12
33 2 NA 13
34 2 NA 14
35 2 NA 15
36     2  16      16
37     2  17      17
38 2 NA 18
39 2 NA 19
40 2 NA 20
41 2 NA 21
42     2  22      22
43 2 NA 23
44 2 NA 24
45 2 NA 25

虽然这是可行的,但它似乎不是很优雅,对于包含许多分组变量的非常大的数据集来说可能很慢。我很好奇是否有一种更“整洁”的方式来做到这一点。

你可以做如下事情:

df %>% 
  group_by(Group) %>%
  mutate(newseq  = seq_along(Group) + (first(na.omit(Seq)) - sum(cumall(is.na(Seq)))) - 1) %>% 
  ungroup()

所有这些都做同样的事情:通过第一个非NA值和它之前的NAs数量的差值来移动序列的开始

输出

   Group   Seq newseq
   <int> <int>  <dbl>
 1     1    NA      3
 2     1    NA      4
 3     1    NA      5
 4     1     6      6
 5     1     7      7
 6     1     8      8
 7     1    NA      9
 8     1    10     10
 9     1    11     11
10     1    NA     12
# ... with 35 more rows
Group-Seq-newseq
1 NA 3
2 1 NA 4
3 1 NA 5
4     1     6      6
5     1     7      7
6     1     8      8
7 1 NA 9
8     1    10     10
9     1    11     11
10 1 NA 12
# ... 还有35行

首先创建行号,然后取
Seq
行号的
max
差值,并添加到行号中:

  dat1 %>%
    group_by(Group) %>%
    mutate(rn = row_number(),
           Seq = rn + max(Seq - rn, na.rm = TRUE)) %>% 
    ungroup() %>%
    select(-rn)
输出:

  Group   Seq
   <dbl> <int>
 1     1     3
 2     1     4
 3     1     5
 4     1     6
 5     1     7
 6     1     8
 7     1     9
 8     1    10
 9     1    11
10     1    12
11     1    13
12     1    14
13     1    15
14     1    16
15     1    17
16     1    18
17     1    19
18     1    20
19     2    -1
20     2     0
21     2     1
22     2     2
23     2     3
24     2     4
25     2     5
26     2     6
27     2     7
28     2     8
29     2     9
30     2    10
31     2    11
32     2    12
33     2    13
34     2    14
35     2    15
36     2    16
37     2    17
38     2    18
39     2    19
40     2    20
# … with 5 more rows
组顺序
1     1     3
2     1     4
3     1     5
4     1     6
5     1     7
6     1     8
7     1     9
8     1    10
9     1    11
10     1    12
11     1    13
12     1    14
13     1    15
14     1    16
15     1    17
16     1    18
17     1    19
18     1    20
19     2    -1
20     2     0
21     2     1
22     2     2
23     2     3
24     2     4
25     2     5
26     2     6
27     2     7
28     2     8
29     2     9
30     2    10
31     2    11
32     2    12
33     2    13
34     2    14
35     2    15
36     2    16
37     2    17
38     2    18
39     2    19
40     2    20
#…还有5行
数据:

set.seed(5112021)
dat1%
突变(rn=rnorm(45,平均值=0.5,标准差=1),
Seq=ifelse(rn<0.4,NA,Seq))%>%
选择(-rn)%>%
分组依据(分组)%>%
突变(Seq=ifelse(Seq==-1,NA,Seq))

填充
完成
,以及来自tidyr的
嵌套
可能会有所帮助。数据是否总是按正确的顺序排序?是的,数据总是按正确的顺序排序
  dat1 %>%
    group_by(Group) %>%
    mutate(rn = row_number(),
           Seq = rn + max(Seq - rn, na.rm = TRUE)) %>% 
    ungroup() %>%
    select(-rn)
  Group   Seq
   <dbl> <int>
 1     1     3
 2     1     4
 3     1     5
 4     1     6
 5     1     7
 6     1     8
 7     1     9
 8     1    10
 9     1    11
10     1    12
11     1    13
12     1    14
13     1    15
14     1    16
15     1    17
16     1    18
17     1    19
18     1    20
19     2    -1
20     2     0
21     2     1
22     2     2
23     2     3
24     2     4
25     2     5
26     2     6
27     2     7
28     2     8
29     2     9
30     2    10
31     2    11
32     2    12
33     2    13
34     2    14
35     2    15
36     2    16
37     2    17
38     2    18
39     2    19
40     2    20
# … with 5 more rows
set.seed(5112021)
dat1 <- bind_rows(data.frame(Group=1,Seq=(3:20)),
                  data.frame(Group=2,Seq=(-1:25))) %>%
  mutate(rn = rnorm(45,mean=0.5,sd=1),
         Seq = ifelse(rn < 0.4,NA,Seq)) %>% 
  select(-rn) %>% 
  group_by(Group) %>% 
  mutate(Seq = ifelse(Seq==-1,NA,Seq))