Реплицируйте каждую строку данных.кадр и укажите количество повторов для каждой строки


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

каков самый простой способ развернуть первые два столбца данных.рамка выше, так что каждая строка отображается количество раз, указанное в столбце 'freq'?

другими словами, перейти от этого:

df
  var1 var2 freq
1    a    d    1
2    b    e    2
3    c    f    3

для этого:

df.expanded
  var1 var2
1    a    d
2    b    e
3    b    e
4    c    f
5    c    f
6    c    f
5 90

5 ответов:

вот одно из решений:

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

результат:

    var1 var2
1      a    d
2      b    e
2.1    b    e
3      c    f
3.1    c    f
3.2    c    f

использовать expandRows() С :

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

простой синтаксис, очень быстро, работает на data.frame или data.table.

результат:

    var1 var2
1      a    d
2      b    e
2.1    b    e
3      c    f
3.1    c    f
3.2    c    f

старый вопрос, новый глагол в tidyverse:

library(tidyr) # version >= 0.8.0
df <- data.frame(var1=c('a', 'b', 'c'), var2=c('d', 'e', 'f'), freq=1:3)
df %>% 
  uncount(freq)

    var1 var2
1      a    d
2      b    e
2.1    b    e
3      c    f
3.1    c    f
3.2    c    f

решение@neilfws отлично подходит для data.frame, а не data.table s так как им не хватает row.names собственность. Этот подход работает для обоих:

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

код data.table немного чище:

# convert to data.table by reference
setDT(df)
df.expanded <- df[rep(seq(.N), freq), !"freq"]

в случае, если вы должны сделать эту операцию на очень больших данных.кадры я бы рекомендовал преобразовать его в данные.стол и использовать следующие, которые должны работать намного быстрее:

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

посмотреть насколько быстрее это решение:

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