拆分 data.frame 行并打乱顺序
Split data.frame rows and shuffle their order
我有一个 data.frame
这样的:
set.seed(1)
df <- data.frame(id = c("A","B;C","D","E","F;G;H","I"), val1 = rnorm(6), val2 = letters[1:6], stringsAsFactors=F)
有一个 id
列,它的一些值有一个分号,表示它结合了几个 id
,并且它们在其余列中的值是共享的。
对于带有分号的 id 的每一行:
- 我想用分号分隔符
id
拆分
- 根据拆分的
id
行数复制 data.frame
行
- 随机
shuffle
复制顺序data.frame
- 用我在 3 中创建的行替换
df
中的原始行,这样 df
中所有其他行的顺序不变。
这是我的笨拙尝试:
idx <- which(grepl(";",df$id))
l <- lapply(idx, function(i){
ids <- strsplit(df$id[i], split = ";")[[1]]
df.i <- do.call("rbind", replicate(length(ids), df[i,,drop=F], simplify = FALSE))
df.i$id <- ids[permute::shuffle(ids)]
return(df.i)
})
idx.names <- df$id[idx]
for(i in 1:length(idx.names)){
df <- rbind(df[1:(which(df$id == idx.names[i])-1),,drop=F],
l[[i]],
df[(which(df$id == idx.names[i])+1):nrow(df),,drop=F])
}
所以我正在寻找更优雅(可能使用 tidyverse
或 data.table
)和更快的东西。
我们可以用separate_rows
,然后按'val2'分组,sample
row_number()
在slice
library(tidyverse)
df %>%
separate_rows(id) %>%
group_by(val2) %>%
slice(sample(row_number()))
我有一个 data.frame
这样的:
set.seed(1)
df <- data.frame(id = c("A","B;C","D","E","F;G;H","I"), val1 = rnorm(6), val2 = letters[1:6], stringsAsFactors=F)
有一个 id
列,它的一些值有一个分号,表示它结合了几个 id
,并且它们在其余列中的值是共享的。
对于带有分号的 id 的每一行:
- 我想用分号分隔符
id
拆分 - 根据拆分的
id
行数复制data.frame
行 - 随机
shuffle
复制顺序data.frame
- 用我在 3 中创建的行替换
df
中的原始行,这样df
中所有其他行的顺序不变。
这是我的笨拙尝试:
idx <- which(grepl(";",df$id))
l <- lapply(idx, function(i){
ids <- strsplit(df$id[i], split = ";")[[1]]
df.i <- do.call("rbind", replicate(length(ids), df[i,,drop=F], simplify = FALSE))
df.i$id <- ids[permute::shuffle(ids)]
return(df.i)
})
idx.names <- df$id[idx]
for(i in 1:length(idx.names)){
df <- rbind(df[1:(which(df$id == idx.names[i])-1),,drop=F],
l[[i]],
df[(which(df$id == idx.names[i])+1):nrow(df),,drop=F])
}
所以我正在寻找更优雅(可能使用 tidyverse
或 data.table
)和更快的东西。
我们可以用separate_rows
,然后按'val2'分组,sample
row_number()
在slice
library(tidyverse)
df %>%
separate_rows(id) %>%
group_by(val2) %>%
slice(sample(row_number()))