2016-08-25 54 views
2

让我们假设我有以下结构的数据集:如何通过R中的多个条件迭代来提高性能?

  • 我的N个国家N个乘积
  • 我有N个的支付合作伙伴
  • 月数据集包含N个天
  • 我有N个不同的价格,客户可以从

例如选择:

customer.id <- c(1,2,3,4,5,6,7,8) 
product <- c("product1","product2","product1","product2","product1","product2","product1","product2") 
country <- c("country1","country2","country1","country2","country1","country2","country1","country2") 
payment.partner <- c("pp1","pp2","pp1","pp2","pp1","pp2","pp1","pp2") 
day <- c("day1","day2","day1","day2","day1","day2","day1","day2") 
price <- c("price1","price2","price1","price2","price1","price2","price1","price2") 

customer.data <- data.frame(customer.id,product,country,payment.partner,day,price) 
customer.data <- data.table(customer.data) 

假设我想生成一个聚合,例如,为每个组合执行预测算法。为了做到这一点,我找出独特的项目为每个条件和如下重复它:

unique.products <- droplevels(unique(customer.data[,product])) 
unique.countries <- droplevels(unique(customer.data[,country])) 
unique.payment.partners <- droplevels(unique(customer.data[,payment.partner])) 
unique.days <- droplevels(unique(customer.data[,day])) 
unique.prices <- droplevels(unique(customer.data[,price])) 

for(i in seq_along(unique.products)){ 
    temp.data1 <- customer.data[product==unique.products[[i]]] 
    for(j in seq_along(unique.countries)){ 
    temp.data2 <- temp.data1[country==unique.countries[[j]]] 
    for(k in seq_along(unique.payment.partners)){ 
     temp.data3 <- temp.data2[payment.partner==unique.payment.partners[[k]]] 
     for(l in seq_along(unique.days)){ 
     temp.data4 <- temp.data3[day==unique.days[[l]]] 
     for(m in seq_along(unique.prices)){ 
      temp.data5 <- temp.data4[price==unique.prices[[m]]] 
      if(nrow(temp.data5)!=0){ 
      # do your calculations here 
      print(temp.data5) 
      } 
     } 
     } 
    } 
    } 
} 

一般来说,这种代码结构工作正常,但在500万行的应用实际数据时,它变得非常烦人它。我想R在速度和性能方面并不是最好的语言。当然,我过去曾经使用过多核处理器,或试图直接从Hive或MySQL数据仓库中获得这样的聚合。使用另一种语言如C++或Python也是一种选择。

但是,有时候所有这些选项都是不可能的,然后总是会导致我完全相同的处理结构。所以我想了很长一段时间,如果从体系结构的角度来看,有一个更好的,更快的解决方案,因为它是已知的(并且在基准测试时也变得非常清楚),因为循环和频繁的数据选择非常非常慢。

感谢所有意见,提示和可能的解决方案!

+4

我承认一种解释型语言较慢THA ñ编译语言,但我从你的“几乎一般”知识的要求冒犯。如果你不知道如何正确使用它,那不是错误的语言。你也可以写慢C++代码。 – Roland

+0

我并不是故意冒犯任何人。只是R本身并不是设计得超快,而是具有很高的可用性和可访问性。请参阅Ben Webers谈论他的RServer项目,他在其中谈到他有时必须证明将R用于数据科学应用程序是合理的:https://www.youtube.com/watch?v = QGzTEuZvyK4 – jd1338

+3

我完全同意@Roland。关于语言速度的一般声明是错误的。没有经验的R用户经常会得出这样的结论:因为他们运用40多岁的C方法来解决他们的问题,所以速度很慢。 R是一种现代编程语言,需要现代编程技术才能高效。 – RHertel

回答

6

您应该阅读您正在使用的软件包的文档。 Package data.table提供了一些优秀的introductory tutorials

customer.data <- data.frame(customer.id,product,country,payment.partner,day,price) 
library(data.table) 
setDT(customer.data) 
customer.data[, 
       print(customer.data[.I]), #don't do this, just refer to the columns you want to work on 
       by = .(product, country, payment.partner, day, price)] 

当然,一般来说,您不会在这里打印data.table子集,而是直接在特定列上工作。

2

从你的描述(但不是你的代码,我发现难以理解为宗旨,我想你可能要使用`交互功能:

customer.data$grp=droplevels(with(customer.data, 
       interaction(product, country ,payment.partner, day, price))) 
table(customer.data$grp) 
#----------------------- 
product1.country1.pp1.day1.price1 
           4 
product2.country2.pp2.day2.price2 
           4 

然后,您可以使用lapply(split(dat, dat$grp) , analytic_function)创建独立的分析。子集之内,我没有data.table加载,从而表现出对dataframes的方法,但没有理由interaction不应该在data.table世界取得成功:

customer.data[ , grp2 := droplevels(interaction( 
             product, country ,payment.partner, day, price)) ] 
+2

但是您不需要使用data.table创建'interaction',因为它提供(更多)高效的分组。您的解决方案在基于R. – Roland

+2

btw。 'split'接受一系列因素,所以你不需要自己创建交互。 – Roland

+0

data.table路由肯定更高效,并且一旦学习了解基本约定和DT约定之间的差异,语法就会非常直观。 –