Разделите строки data.frame и перетасуйте их порядок - PullRequest
0 голосов
/ 31 января 2019

У меня есть 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 с, а их значения востальные столбцы являются общими.

Для каждой строки с идентификатором с точкой с запятой:

  1. Я хотел бы разделить id разделителем точек с запятой
  2. реплицирует эту data.frame строку на количество id s, которые были разбиты
  3. случайным образом shuffle порядок реплицированных data.frame
  4. заменяет исходную строку в df с той, которую я создал в 3, так что порядок всех других строк в 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) и быстрее.

1 Ответ

0 голосов
/ 31 января 2019

Мы можем использовать separate_rows, затем сгруппировать по 'val2', sample row_number() в slice

library(tidyverse)
df %>% 
   separate_rows(id) %>%
   group_by(val2) %>%
   slice(sample(row_number()))
...