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

R 使列表的每个元素都是自己的行(基于列值的列表),r,dataframe,dplyr,tidyr,R,Dataframe,Dplyr,Tidyr,我有一个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) 南特主题:第1页第2页第3页。 每一页有不同的行数。对于南特,第1页有2行 我想要的是:根据1:nrow序列

我有一个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)
南特主题:第1页第2页第3页。
每一页有不同的行数。对于南特,第1页有2行

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

例如:我需要将Nantes第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
包中的
map
创建
行中的整数序列列表。在此之后,
unest
数据帧
df2
是最终输出

library(tidyverse)

df2 <- df %>%
  mutate(rows = map(rows, seq)) %>%
  unnest()
库(tidyverse)
df2%
突变(行=映射(行,序列))%>%
unnest()

在base R中,您可以

dfNew <- data.frame(subject=rep(df$subject, df$rows),
                    page=rep(df$page, df$rows),
                    rows=sequence(df$rows))
使用
可能会更干净一些:

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

dfNew如果按其他列分组,可以使用
tidyr::complete
seq
来填写缺少的观察结果:

库(tidyverse)
df%
完成(行=序号(行))
df_扩展
#>#tibble:20 x 3
#>#分组:主题,第[6]页
#>主题页行
#>        
#>1布雷斯特11
#>2布雷斯特12
#>3布雷斯特1 3
#>4布雷斯特14
#>5布雷斯特15
#>6布雷斯特16
#>7布雷斯特2 1
#>8布雷斯特2
#>9南特1
#>10南特12
#>11南特2 1
#>12南特2
#>13南特2 3
#>14南特3 1
#>15南特3 2
#>16南特3 3
#>17南特3 4
#>18雷恩1
#>19雷恩1 2
#>20雷恩1 3

这种方法的优点是,如果一个
主题
/
页面
组合已经部分展开,它就不会被复制。

只要它不是一个海量数据框架,
应用
也可以工作

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)))

映射(行,序列)
会有点simpler@alistaire谢谢分享你的想法。我会根据你的建议更新答案。比
do.call(rbind,lappy(split(df,paste(df$subject,df$page)),function(a)data.frame(subject=a$subject,page=a$page,rows=sequence(a$rows)))好得多。
@d.b是的,我喜欢
lappy
/
split
方法,但在某些问题上,它可能相当沉重;您已将
页面
转换为数字因子。
dfNew <- with(df, data.frame(subject=rep(subject, rows),
                             page=rep(page, rows),
                             rows=sequence(rows)))
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)))