复制data.frame的每一行,并指定每行的复制次数

df <- data.frame(var1=c('a', 'b', 'c'), var2=c('d', 'e', 'f'), freq=1:3) 

什么是最简单的方法来扩大上面的data.frame的前两列,以便每一行出现在“freq”列中指定的次数?

换句话说,从这个angular度来看:

 df var1 var2 freq 1 ad 1 2 be 2 3 cf 3 

对此:

 df.expanded var1 var2 1 ad 2 be 3 be 4 cf 5 cf 6 cf 

这里有一个解决scheme:

 df.expanded <- df[rep(row.names(df), df$freq), 1:2] 

结果:

  var1 var2 1 ad 2 be 2.1 be 3 cf 3.1 cf 3.2 cf 

使用splitstackshape包中的expandRows()

 library(splitstackshape) expandRows(df, "freq") 

简单的语法,非常快,适用于data.framedata.table

结果:

  var1 var2 1 ad 2 be 2.1 be 3 cf 3.1 cf 3.2 cf 

@ neilfws的解决scheme适用于data.frame ,但不适用于data.table因为它们缺lessrow.names属性。 这种方法适用于:

 df.expanded <- df[rep(seq(nrow(df)), df$freq), 1:2] 

对于data.table虽然你需要添加with=F并可以select删除df$

 dt <- data.table(df) dt.expanded <- dt[rep(seq(.N), freq), !"freq", with=F] 

万一你必须在非常大的data.frames上做这个操作,我build议把它转换成一个data.table,并使用下面的代码,它应该运行得更快:

 library(data.table) dt <- data.table(df) dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")] dt.expanded[ ,freq := NULL] dt.expanded 

看看这个解决scheme有多快

 df <- data.frame(var1=1:2e3, var2=1:2e3, freq=1:2e3) system.time(df.exp <- df[rep(row.names(df), df$freq), 1:2]) ## user system elapsed ## 4.57 0.00 4.56 dt <- data.table(df) system.time(dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")]) ## user system elapsed ## 0.05 0.01 0.06