【发布时间】:2017-04-27 13:46:35
【问题描述】:
我的数据看起来像这样:
char_column date_column1 date_column2 integer_column
415 18JT9R6EKV 2014-08-28 2014-09-06 1
26 18JT9R6EKV 2014-12-08 2014-12-11 2
374 18JT9R6EKV 2015-03-03 2015-03-09 1
139 1PEGXAVCN5 2014-05-06 2014-05-10 3
969 1PEGXAVCN5 2014-06-11 2014-06-15 2
649 1PEGXAVCN5 2014-08-12 2014-08-16 3
我想执行一个循环来检查每一行与前一行,并在某些条件下为它们分配相同的数字(这样我以后可以对它们进行分组),关键是如果日期段足够接近,我会将它们折叠成一个片段。
我的尝试如下:
i <- 1
z <- 1
v <- 1
for (i in 2:nrow(df)){
z[i] <- ifelse(df[i,'char_column'] == df[i-1,'char_column'],
ifelse((df[i,'date_column1'] - df[i-1,'date_column2']) <= 5,
ifelse(df[i,'integer_column'] == df[i-1,'integer_column'],
v, v<- v+1),
v <- v+1),
v <- v+1)}
df$grouping <- z
然后我将使用 min(date_column1) 和 max(date_column2) 进行分组。
这种方法非常适用于 100,000 行(22.86 秒) 但是对于一百万行:33.18 分钟!我有超过 60m 行要处理, 有什么方法可以让流程更高效?
PS:要生成类似的表,您可以使用以下代码:
x <- NULL
for (i in 1:200) { x[i] <- paste(sample(c(LETTERS, 1:9), 10), collapse = '')}
y <- sample((as.Date('2014-01-01')):as.Date('2015-05-01'), 1000, replace = T)
y2 <- y + sample(1:10)
df <- data.frame(char_column = sample(x, 1000, rep = T),
date_column1 = as.Date(y, origin = '1970-01-01'),
date_column2 = as.Date(y2,origin = '1970-01-01'),
integer_column = sample(1:3,1000, replace = T),
row.names = NULL)
df <- df[order(df$char_column, df$date_column1),]
【问题讨论】:
-
快速解决一些速度提升的方法是预先分配存储向量 z。添加
z <- numeric(nrow(df)); z[1] <- 1。 -
使用随机过程创建示例时,请使用
set.seed在解决方案中获得一致的结果。 -
@JasonMorgan 由于这是一个效率问题,因此所需的输出等于原始脚本的输出。希望,只是更快。
-
@user4970610 data.table 有
shift函数df$grouping <- rleid(df$char_column, df$date_column1-shift(df$date_column2)<=5, df$integer_column==shift(df$integer_column))也许? -
@user4970610 发布了一个可能适合您需求的解决方案