【问题标题】:R - Efficiently Separate Groups in Data Frame [duplicate]R - 在数据框中有效地分离组[重复]
【发布时间】:2017-09-10 14:36:03
【问题描述】:

我有以下形式的用户统计数据集:

df
   user       date   group
1    X 2017-06-21   S;Y;J
2    Y 2017-06-09 Y;F;P;C
3    R 2017-12-29     K;A
4    Q 2017-08-31     W;I
5    B 2018-01-30   P;M;E

可以通过以下方式生成:

set.seed(10)
n = 5
dates <- seq.Date(as.Date("2017-04-01"), as.Date("2018-05-01"), by=1)
df <- data.frame(user = sample(LETTERS, n, replace=TRUE),
             date = sample(dates, n, replace=TRUE))

df$group <- "A"
for(i in 1:n){
df$group[i] <- paste(sample(LETTERS, sample(1:5, 1, replace=FALSE), 
                       replace=FALSE), collapse=";")
}

我想拆分和扩展group 列,使其与给定的日期和用户匹配。例如,用户X2017-06-21 上的三个组进行了交互,我希望将它们作为三个单独的条目而不是一个。我有适用于此的代码,但我正在寻找一种更快、更 R 友好的复制方式。我目前的解决方案是:

# Get the number of groups for each entry
n_groups <- 1 + gsub("[^;]", "", df$group) %>% nchar()
# Get the index for the entries with multiple groups
index <- which(n_groups > 1)
# Get a new vector of dates and users
dates <- integer(sum(n_groups))
class(dates) <- "Date"
users <- vector(mode='character', 
                length = sum(n_groups))

k <- 1
for(i in 1:length(n_groups)){
  for(j in 1:n_groups[i]){
    dates[k] <- df$date[i]
    users[k] <- as.character(df$user[i])
    k <- k + 1
  }
}

df2 <- data.frame(date = dates, user = users,
                  group = unlist(strsplit(df$group, split = ";")))
df2
         date user group
1  2017-06-21    X     S
2  2017-06-21    X     Y
3  2017-06-21    X     J
4  2017-06-09    Y     Y
5  2017-06-09    Y     F
6  2017-06-09    Y     P
7  2017-06-09    Y     C
8  2017-12-29    R     K
9  2017-12-29    R     A
10 2017-08-31    Q     W
11 2017-08-31    Q     I
12 2018-01-30    B     P
13 2018-01-30    B     M
14 2018-01-30    B     E

【问题讨论】:

  • 链接帖子中 matt-lundberg 的基本 R 答案的模拟是 temp &lt;- strsplit(df$group, split=";"); cbind(df[rep(seq_along(df$user), lengths(temp)),], "newgroup"=unlist(temp))。此版本保留了原始组向量,可以使用grep 或静态删除。

标签: r grouping


【解决方案1】:
library(dplyr)
library(tidyr)

df2 <- df %>% 
  mutate(group = strsplit(group, split = ";")) %>%
  unnest(group) %>%
  select(date, user, group)

【讨论】:

  • 太棒了!快几个数量级!
  • @hubbs5 但是,它不是最快的。我用n = 10000 行的样本数据对7 种不同的方法进行了基准测试。最快的是 library(data.table); setDT(df)[, .(group = unlist(strsplit(as.character(group), ";", fixed = TRUE))), by = .(date, user)],其次是 splitstackshape::cSplit(df, "group", ";", direction = "long") 和 lmo 的 solution。 ycw 的解决方案比最快的解决方案慢 2.5 倍。不幸的是,我无法发布所有详细信息的答案。
  • @hubbs5 我已经为欺骗目标Split comma-separated column into separate rows 发布了benchmark results。对于大型问题,data.tabledplyr/tidyr 快很多。
  • @Uwe Block 感谢您进行全面的基准比较。
猜你喜欢
  • 2019-06-17
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
相关资源
最近更新 更多