使列表的每个元素都是自己的行(基于列值的列表)

Make each element of a list is own row (list based on columns values)

我有这个 data.frame 对象:

subject <- c("Nantes", "Nantes", "Nantes", "Brest", "Brest", "Rennes")
page <- c(1, 2, 3, 1, 2, 1)
rows <- c(2, 3, 4, 6, 2, 3)
df <- data.frame (subject,page, rows)

这是输出:

subject   page    rows 
Nantes    1       2     
Nantes    2       3     
Nantes    3       4     
Brest     1       6     
Brest     2       2     
Rennes    1       3

南特的主题:第 1 页,第 2 页,第 3 页。
每页有不同的行数。对于南特,page1 有 2 行。

我想要的:根据 1:nrow 序列复制每一行。

例如:我需要复制南特第 1 页两次

subject   page    rows 
Nantes    1       1     
Nantes    1       2     
Nantes    2       1 
Nantes    2       2
Nantes    2       3
Nantes    3       1
Nantes    3       2
Nantes    3       3
Nantes    3       3
Nantes    3       4 
Brest     1       1
Brest     1       2 
Brest     1       3 
Brest     1       4 
Brest     1       5 
Brest     1       6     
Rennes    1       1
Rennes    1       2
Rennes    1       3

基于我可以使用unnest函数但无法解决我的问题

我们可以使用 purrr 包中的 maprows 中创建一个整数序列列表。之后,unnest 数据框。 df2 是最终输出。

library(tidyverse)

df2 <- df %>%
  mutate(rows = map(rows, seq)) %>%
  unnest()

在基础 R 中,你可以这样做

dfNew <- data.frame(subject=rep(df$subject, df$rows),
                    page=rep(df$page, df$rows),
                    rows=sequence(df$rows))

rep 在第二个位置使用矢量参数,将第一个位置的元素重复相应的次数。 sequence 具有整数向量 returns 从 1 到每个值计数。

dfNew
   subject page rows
1   Nantes    1    1
2   Nantes    1    2
3   Nantes    2    1
4   Nantes    2    2
5   Nantes    2    3
6   Nantes    3    1
7   Nantes    3    2
8   Nantes    3    3
9   Nantes    3    4
10   Brest    1    1
11   Brest    1    2
12   Brest    1    3
13   Brest    1    4
14   Brest    1    5
15   Brest    1    6
16   Brest    2    1
17   Brest    2    2
18  Rennes    1    1
19  Rennes    1    2
20  Rennes    1    3

使用 with 可能更干净一些:

dfNew <- with(df, data.frame(subject=rep(subject, rows),
                             page=rep(page, rows),
                             rows=sequence(rows)))

如果按其他列分组,可以使用 tidyr::completeseq 来填充缺失的观察值:

library(tidyverse)

df <- data_frame(subject = c("Nantes", "Nantes", "Nantes", "Brest", "Brest", "Rennes"),
                 page = c(1,2,3,1,2, 1),
                 rows = c(2, 3, 4, 6, 2, 3))

df_expanded <- df %>% 
    group_by(subject, page) %>% 
    complete(rows = seq(rows))

df_expanded
#> # A tibble: 20 x 3
#> # Groups:   subject, page [6]
#>    subject  page  rows
#>      <chr> <dbl> <dbl>
#>  1   Brest     1     1
#>  2   Brest     1     2
#>  3   Brest     1     3
#>  4   Brest     1     4
#>  5   Brest     1     5
#>  6   Brest     1     6
#>  7   Brest     2     1
#>  8   Brest     2     2
#>  9  Nantes     1     1
#> 10  Nantes     1     2
#> 11  Nantes     2     1
#> 12  Nantes     2     2
#> 13  Nantes     2     3
#> 14  Nantes     3     1
#> 15  Nantes     3     2
#> 16  Nantes     3     3
#> 17  Nantes     3     4
#> 18  Rennes     1     1
#> 19  Rennes     1     2
#> 20  Rennes     1     3

这种方法的优点是,如果一个 subject/page 组合已经部分展开,则不会重复。

只要不是很大data.frame,apply也可以

do.call(rbind, apply(X = df, MARGIN = 1, function(x)
    data.frame(subject = x[1],
               page = as.numeric(x[2]),
               rows = sequence(x[3]),
               row.names = NULL)))