替代使用For循环计算弹性

时间:2015-07-23 14:33:08

标签: r for-loop

我写了一段代码来计算大约200k产品的弹性。弹性计算正常,但已经超过15个小时,并且该过程仍在运行。我看到正在创建新对象。如果不使用for循环,有没有更快的替代方法?

以下是我的代码:

    sku_list <- unique(transact_data4$productId)
    elasticity_values <- data.frame()

    for (i in 1:length(sku_list)){
     test_sku <- subset(transact_data4, productId==sku_list[i])
     m1 <- lm(formula=sales~price, data= test_sku)
     coeffs <- as.data.frame(m1[[1]])
     gradient<- coeffs[2,1]
     gradient_final <- ifelse(is.na(gradient), -1, gradient)
     mean_price <- mean(test_sku$price)
     mean_sales <- mean(test_sku$sales)
     elasticity <- gradient_final*mean_price/mean_sales
     sku_elasticity <- cbind(sku_list[i],elasticity)
     elasticity_values <- rbind(elasticity_values,sku_elasticity)
    }
colnames(elasticity_values)[colnames(elasticity_values)=="V1"] <- "productId" 

以下是一个示例数据集:

transact_data <- data.frame(productId=c('A', 'A','A', 'A','A', 'A','B', 'B','B', 'B','B', 'B'),
                  price=c(10, 10.5, 11, 12,10, 9,
                    10, 11, 13, 11,12.5, 11),
                    sales =c(100,93,90,85,99,110,101,95,80,103,82,102), stringsAsFactors=FALSE)

结果:

  productId         elasticity
1         A -0.913344887348354
2         B  -1.03051724343462

有没有更快的方法来实现这一点而不使用for循环? 显然,由于样本较小(只有2个productId),因此运行速度很快。 但我正试图以超过20万的productId运行它。

谢谢。

2 个答案:

答案 0 :(得分:1)

<强>代码

library(dplyr)

transact_data %>% group_by(productId) %>%
   do(mod = lm(sales ~ price, data = .), 
      mean.price = mean(.$price), 
      mean.sales = mean(.$sales)) %>%
   summarise(productId  = productId,
             elasticity = ifelse(is.na(coef(mod)[2]), -1, coef(mod)[2]) * 
                          mean.price / mean.sales)

#   productId elasticity
# 1         A -0.9133449
# 2         B -1.0305172

<强>解释

使用library(dplyr),您可以方便地进行此分组计算:

  • %>%是链接运算符,通过输入左参数作为右边函数的第一个参数,使代码更具可读性
  • group_by告诉您要按列productId
  • 分组的下一个命令
  • do用于计算模型和所需的平均值,在do范围内,您使用点.来引用整个data.frame
  • summarise最后通过计算弹性来总结您的计算

有关详细信息,请查看vignette("introduction")

顺便提一下,你的代码很慢,因为你使用循环并在它上面增加循环中的数据。查看http://www.burns-stat.com/pages/Tutor/R_inferno.pdf有关常见陷阱的一些教程。

答案 1 :(得分:0)

此处您可以优化代码

1)函数apply,sapply,...比for循环更快

2)如果使用大数据,rbind和cbind会很慢。我建议你创建你的大数据。(空),已经有很多列和行,然后填充它。

玩得开心!