在R中矢量化for-loop以创建具有不同长度的字符串

时间:2015-10-29 04:07:37

标签: r vectorization

我创建了一个示例R脚本来显示我的问题:

test.df <- data.frame(uid=c('x001','x002','x003'),
                      start_date=c('2015-01-02','2015-03-05','2015-07-09'),
                      end_date=c('2015-01-07','2015-03-07','2015-07-16'),
                      stringsAsFactors=FALSE) 
test.df[,'start_date'] <- as.Date(test.df[,'start_date']) 
test.df[,'end_date'] <- as.Date(test.df[,'end_date']) 
for (loop in (1:nrow(test.df))) {   
    test.df[loop,'output'] <- paste(seq(test.df[loop,'start_date'],test.df[loop,'end_date'],by = 1),collapse=';') 
}

我需要创建不同长度的日期字符串,我只能考虑使用for-loop来解决我的问题,但我有大约70K需要处理字符串的情况,是否有任何加速它的方法?

更新01

感谢@akrun的回答,我进一步修改了我的问题如下:

library(dplyr)

test.df <- data.frame(uid=c('x001','x002','x003'),
                      start_date=c('2015-01-02','2015-03-05','2015-07-09'),
                      end_date=c('2015-01-07','2015-03-07','2015-07-16'),
                      stringsAsFactors=FALSE)
test.df[,'start_date'] <- as.Date(test.df[,'start_date'])
test.df[,'end_date'] <- as.Date(test.df[,'end_date'])

# Part A
for (loop in (1:nrow(test.df))) {   
  test.df[loop,'output'] <- paste(seq(test.df[loop,'start_date'],test.df[loop,'end_date'],by = 1),collapse=';') 
}

# Part B
test.mod <- group_by(test.df,uid) %>%
  do({df <- data.frame(.)
  output.df <- data.frame(uid=df[1,'uid'],
                          date=unlist(strsplit(df[,'output'],';')))
  data.frame(output.df)
  })

现在Part A已修复,但无论如何还要加速Part B?或者我应该将Part APart B合并在一起吗?请赐教,data.table对我来说是新的。

2 个答案:

答案 0 :(得分:2)

我们可以将'test.df'转换为'data.table'(setDT(test.df)),按'uid'分组,我们得到'{1}}'start_date','end_date'和seq元素在一起。

paste

更新

对于B部分,如果我们不library(data.table) setDT(test.df)[,paste(seq(start_date, end_date, by = '1 day'), collapse=';') , uid] ,则它是一个双列数据集

paste

答案 1 :(得分:0)

以下是使用

进行操作的方法
test.df <- data.frame(uid=c('x001','x002','x003'),
                      start_date=c('2015-01-02','2015-03-05','2015-07-09'),
                      end_date=c('2015-01-07','2015-03-07','2015-07-16'),
                      stringsAsFactors=FALSE) 

test.df$output <- apply(test.df, 1, function(x) paste(seq(as.Date(x[2]), as.Date(x[3]), by = 1), collapse=';'))