2017-04-14 29 views
1

我有以下形式的用户的统计信息的数据组:的R - 在数据帧有效地分离群组

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=";") 
} 

我想要分割并扩展:

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 

可与生成group列,以便它与给定的日期和用户相匹配。例如,用户X已与2017-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 
+2

亚光伦德伯格的基础R答案中的链接后的模拟是'温度< - strsplit(DF $基,分裂= “;”); cbind(df [rep(seq_along(df $ user),lengths(temp)),],“newgroup”= unlist(temp))'。这个版本保留了可以用'grep'或静态删除的原始组向量。 – lmo

回答

2
library(dplyr) 
library(tidyr) 

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

太棒了!数量级更快! – hubbs5

+3

@ hubbs5但是,这不是最快的。我用'n = 10000'行的样本数据对7种不同的方法进行了基准测试。最快的是'library(data.table); setDT(df)[,。(group = unlist(strsplit(as.character(group),“;”,fixed = TRUE))), by =。(date,user)]''splitchedackshape :: cSplit (df,“group”,“;”,direction =“long”)'和lmo的[解决方案](http://stackoverflow.com/questions/43409756/r-efficiently-separate-groups-in-data-frame# comment73880215_43409756)。 ycw的解决方案比最快的解决方案慢2.5倍。不幸的是,我无法提供所有细节的答案。 – Uwe

+3

@ hubbs5我发布了[基准测试结果](http://stackoverflow.com/a/43431847/3817004)为目标[_分隔逗号分隔列到单独rows_](http://stackoverflow.com/questions/13773770 /分逗号分隔的柱 - 进入 - 单独-行)。对于大型问题,'data.table'比'dplyr' /'tidyr'快得多。 – Uwe