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

wkm*_*or1 128 r replicate dataframe

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

扩展上面data.frame的前两列的最简单方法是什么,以便每行显示"freq"列中指定的次数?

换句话说,从这里开始:

df
  var1 var2 freq
1    a    d    1
2    b    e    2
3    c    f    3
Run Code Online (Sandbox Code Playgroud)

对此:

df.expanded
  var1 var2
1    a    d
2    b    e
3    b    e
4    c    f
5    c    f
6    c    f
Run Code Online (Sandbox Code Playgroud)

nei*_*fws 154

这是一个解决方案:

df.expanded <- df[rep(row.names(df), df$freq), 1:2]
Run Code Online (Sandbox Code Playgroud)

结果:

    var1 var2
1      a    d
2      b    e
2.1    b    e
3      c    f
3.1    c    f
3.2    c    f
Run Code Online (Sandbox Code Playgroud)

  • 对于大的`data.frame`,更有效的是用`seq.int(1,nrow(df))`或`seq_len(nrow(df))`替换`row.names(df)`. (18认同)
  • 1:2硬编码用于此示例的解决方案,1:ncol(df)将适用于任意数据帧。 (3认同)
  • 伟大的!我总是忘记你可以这样使用方括号。我一直在考虑索引只是为了子集或重新排序。我有另一个解决方案,它远没有那么优雅,而且效率无疑也更低。无论如何,我可能会发布以便其他人可以比较。 (2认同)

ein*_*nar 47

旧问题,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
Run Code Online (Sandbox Code Playgroud)


Sam*_*rke 43

expandRows()splitstackshape包中使用:

library(splitstackshape)
expandRows(df, "freq")
Run Code Online (Sandbox Code Playgroud)

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

结果:

    var1 var2
1      a    d
2      b    e
2.1    b    e
3      c    f
3.1    c    f
3.2    c    f
Run Code Online (Sandbox Code Playgroud)


Max*_*nis 20

@ neilfws的解决方案适用于data.frames,但不适用于data.tables,因为它们缺少row.names属性.这种方法适用于:

df.expanded <- df[rep(seq(nrow(df)), df$freq), 1:2]
Run Code Online (Sandbox Code Playgroud)

代码data.table是一个有点清洁:

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

  • 另一种选择:`df [rep(seq(.N),freq)] [,freq:= NULL]` (4认同)

rdo*_*nas 7

我知道情况并非如此,但如果您需要保留原始 freq 列,则可以将另一种tidyverse方法与rep

library(purrr)

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

df %>% 
  map_df(., rep, .$freq)
#> # A tibble: 6 x 3
#>   var1  var2   freq
#>   <fct> <fct> <int>
#> 1 a     d         1
#> 2 b     e         2
#> 3 b     e         2
#> 4 c     f         3
#> 5 c     f         3
#> 6 c     f         3
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.3.0)于 2019 年 12 月 21 日创建

  • 或者只是在 `uncount()` 中使用 `.remove = FALSE` (4认同)

Ron*_*hah 6

我们重复每行数次的另一种dplyr选择slicefreq

library(dplyr)

df %>%  
  slice(rep(seq_len(n()), freq)) %>% 
  select(-freq)

#  var1 var2
#1    a    d
#2    b    e
#3    b    e
#4    c    f
#5    c    f
#6    c    f
Run Code Online (Sandbox Code Playgroud)

seq_len(n()) 部分可以用以下任何一种替换。

df %>% slice(rep(1:nrow(df), freq)) %>% select(-freq)
#Or
df %>% slice(rep(row_number(), freq)) %>% select(-freq)
#Or
df %>% slice(rep(seq_len(nrow(.)), freq)) %>% select(-freq)
Run Code Online (Sandbox Code Playgroud)


von*_*njd 5

如果您必须在非常大的 data.frames 上执行此操作,我建议将其转换为 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
Run Code Online (Sandbox Code Playgroud)

看看这个解决方案有多快:

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
Run Code Online (Sandbox Code Playgroud)


M--*_*M-- 5

另一种可能性是使用tidyr::expand

library(dplyr)
library(tidyr)

df %>% group_by_at(vars(-freq)) %>% expand(temp = 1:freq) %>% select(-temp)
Run Code Online (Sandbox Code Playgroud)
#> # A tibble: 6 x 2
#> # Groups:   var1, var2 [3]
#>   var1  var2 
#>   <fct> <fct>
#> 1 a     d    
#> 2 b     e    
#> 3 b     e    
#> 4 c     f    
#> 5 c     f    
#> 6 c     f
Run Code Online (Sandbox Code Playgroud)

vonjd 答案的单行版本:

#> # A tibble: 6 x 2
#> # Groups:   var1, var2 [3]
#>   var1  var2 
#>   <fct> <fct>
#> 1 a     d    
#> 2 b     e    
#> 3 b     e    
#> 4 c     f    
#> 5 c     f    
#> 6 c     f
Run Code Online (Sandbox Code Playgroud)
#>    var1 var2
#> 1:    a    d
#> 2:    b    e
#> 3:    b    e
#> 4:    c    f
#> 5:    c    f
#> 6:    c    f
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.2.1)于 2019-05-21 创建