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)
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.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
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)
我知道情况并非如此,但如果您需要保留原始 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 日创建
我们重复每行数次的另一种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)
如果您必须在非常大的 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)
另一种可能性是使用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 创建
| 归档时间: |
|
| 查看次数: |
87771 次 |
| 最近记录: |