r语言 - 我如何添加额外的行,以跨所有组在tibble使用tidyverse的每列?



如何为数据框架中的每个组id的所有列(除了分组变量)添加额外的行?

数据:

> library(tidyverse)
> df <- tibble(id = c("A", "B", "C"), day = c(3, 1, 2), station = c(10, 9, 2))
> df
# A tibble: 3 × 3
id      day station
<chr> <dbl>   <dbl>
1 A         3      10
2 B         1       9
3 C         2       2
预期输出:

# A tibble: 6 × 3
# Groups:   id [3]
id      day station
<chr> <dbl>   <dbl>
1 A         2       9
2 A         3      10
3 B         0       8
4 B         1       9
5 C         1       1
6 C         2       2

我可以改变day使用:

> df %>% group_by(id) %>% complete(day = (day - 1):day)
# A tibble: 6 × 3
# Groups:   id [3]
id      day station
<chr> <dbl>   <dbl>
1 A         2      NA
2 A         3      10
3 B         0      NA
4 B         1       9
5 C         1      NA
6 C         2       2

但是我不能使用mutate适当地为station做这个,因为我不知道如何正确地引用complete内的每列:

失败:

> df %>% 
+ group_by(id) %>% 
+ mutate(across(c("day", "station"), complete((.x - 1):.x)))

简化ThomasIsCoding的答案:

df %>%
group_by(id) %>%
summarize(across(day:station, ~ .x - 1:0))

我不认为在这里使用complete()有任何优势,如果你只是想增加值,没有一个特定的范围为每组。

这适用于您想要的输出:

df %>% 
bind_rows(df %>% mutate(across(c('day', 'station'), ~.x - 1 ))) %>% 
arrange(id)
# A tibble: 6 × 3
# id      day station
# <chr> <dbl>   <dbl>
# 1 A         3      10
# 2 A         2       9
# 3 B         1       9
# 4 B         0       8
# 5 C         2       2
# 6 C         1       1

这里我添加了相同的数据框,但列发生了变化,所以:

df %>% mutate(across(c('day', 'station'), ~.x - 1 ))

:

# A tibble: 3 × 3
id      day station
<chr> <dbl>   <dbl>
1 A         2       9
2 B         0       8
3 C         1       1

然后使用bind_rows,我将这些行附加到原始数据帧,这带来:

# A tibble: 6 × 3
id      day station
<chr> <dbl>   <dbl>
1 A         3      10
2 B         1       9
3 C         2       2
4 A         2       9
5 B         0       8
6 C         1       1

最后,我只是安排id,使行看起来像你的例子。

data.table选项简化了问题

> library(data.table)
> setDT(df)[, lapply(.SD, `-`, 1:0), id]
id day station
1:  A   2       9
2:  A   3      10
3:  B   0       8
4:  B   1       9
5:  C   1       1
6:  C   2       2

或者,使用list+unnest

library(tidyr)
df %>%
group_by(id) %>%
mutate(across(day:station, ~ list(.x - (1:0)))) %>%
unnest(day:station) %>%
ungroup()

,

# A tibble: 6 × 3
id      day station
<chr> <dbl>   <dbl>
1 A         2       9
2 A         3      10
3 B         0       8
4 B         1       9
5 C         1       1
6 C         2       2

相关内容

最新更新