我有一个用户统计数据集,格式如下:
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
列拆分和扩展,以便与给定的日期和用户匹配。例如,用户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
temp <- strsplit(df$group, split=";"); cbind(df[rep(seq_along(df$user), lengths(temp)),], "newgroup"=unlist(temp))
。这个版本保留了原始的组向量,可以使用grep
或静态地删除。 - lmo