简体   繁体   English

如何使用 tidyverse 向 tibble 中所有组的每一列添加额外的行?

[英]How do I add extra rows to each column across all groups in tibble using tidyverse?

How do I add extra rows for all columns (except the grouping variable) for each group id in the data frame?如何为数据框中每个组id的所有列(分组变量除外)添加额外的行?

Data:数据:

> 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

Expected output:预计 output:

# 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

I could change day using:我可以使用以下方式更改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

But I couldn't use mutate appropriately to do this for station as well as since I don't know how to refer to each column inside complete properly:但是我不能适当地使用mutate来为station做这个,因为我不知道如何正确地引用里面的每一列complete

Failed attempt:失败的尝试:

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

Simplifying ThomasIsCoding's answer:简化 ThomasIsCoding 的回答:

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

I don't think it has any advantage to use complete() here if you just want to increment values and do not have a specific range for each group.如果您只想增加值并且没有为每个组指定特定范围,我认为在这里使用complete()没有任何优势。

This works for your desired output:这适用于您想要的 output:

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

Here I'm appending the same dataframe but with mutated columns, so:在这里,我附加了相同的 dataframe 但带有变异的列,因此:

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

Is:是:

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

Then with bind_rows , I'm appending those rows to the original data frame, which brings:然后使用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

Finally I just arrange by id so the rows look like your example.最后我只是按id排列,所以行看起来像你的例子。

A data.table option simplifies the problem 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

Or, using list + unnest或者,使用list + unnest

library(tidyr)

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

which gives这使

# 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

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

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