【问题标题】:Writing for loop in a better way in R在 R 中以更好的方式编写 for 循环
【发布时间】:2018-12-04 09:16:24
【问题描述】:

我正在为我的问题寻找优化的解决方案,我确实有解决方案,但需要时间。

有 2 个数据框:

Df1: 
Hid     MST     Date      Percent  year_1_back     Avg_Percent 
1        1    01-01-2018     .90    01-01-2017     0

DF1 共有 19,900 条记录

DF2:
Hid     MST     Date      Percent  
1        1    01-01-2017     .90   
1        1    02-01-2017     .91

我在 DF2 中的数据直到今天

所以,现在我想更新 DF1 中的 Avg_Percent 列,方法是从 DF2 中获取 1 年的数据以及百分比的平均值。

现有逻辑:

for(row in 1:nrow(DF1)){
  #row = 1
  hid <- DF1[row,]$hid
  mst <- DF1[row,]$mst
  startdate <- DF1[row,]$year_1_back
  enddate <- DF1[row,]$Date
  test1 <- DF2[which(DF2$Date>= startdate & DF2$Date<= enddate & DF2$MarketSegmentType == mst & DF2$hid== hid),]
  AVG <- mean(test1$Percet)
  DF1[row,]$Avg_Percent <- AVG
}

这给了我结果,但执行需要很长时间。我认为 dplyr 会很有用,但不知道如何使用该功能。

我正在寻找一些比现有代码更快的代码。

【问题讨论】:

  • 一般来说,purrr 包中的map 函数是替换for-loop 的好选择
  • 你有什么例子,我可以举个例子吗?
  • 请注意,purrr 系列函数(如 *apply 系列)只是隐藏了 for 循环,只是为了清楚起见。
  • 对不起,我误读了您的第一条评论,尝试添加有关您的数据的更多详细信息,一个可重复的示例应该会有所帮助。在小样本上尝试使用dput
  • 如果没有更大的测试数据样本,很难提供帮助,但这可以通过以下步骤在dplyr 中快速轻松地完成:首先使用DF1time_period 变量分配给DF2 中的每个观察结果。然后,在DF2 上,使用group_by(hid, mst, time_period)summarise with function = mean 来获得所需的结果。

标签: r dplyr


【解决方案1】:

我们可以在df1.Date &gt;= df2.Date AND df1.year_1_back &lt;= df2.Date的基础上使用sqldf进行JOIN,然后进行分组和总结。

library(dplyr)
library(sqldf)
sqldf::sqldf("SELECT a.Hid AS a_Hid, a.MST As a_MST, a.Date, a.year_1_back, b.Hid, b.MST, b.Percent, b.Date AS DF2DATE
FROM df1 a
JOIN df2 b on a.Hid = b.Hid AND a.MST = b.MST AND
a.Date >= b.Date AND a.year_1_back <= b.Date") %>% 
       as_tibble() %>% group_by(a_Hid, a_MST, Date, year_1_back) %>%
       summarise(Percent=mean(Percent, na.rm = TRUE))

# A tibble: 1 x 5
# Groups:   a_Hid, a_MST, Date [?]
     a_Hid a_MST Date       year_1_back Percent
     <int> <int> <date>     <date>        <dbl>
  1     1     1 2018-01-01 2017-01-01    0.905

【讨论】:

  • 建议在 sql 中完成所有操作(而不是混合包),如下所示:library(sqldf); sqldf("SELECT a.Hid, a.MST, a.Date, a.year_1_back, avg(b.Percent) AS Percent FROM DF1 a LEFT JOIN DF2 b on a.Hid = b.Hid AND a.MST = b.MST AND b.Date BETWEEN a.year_1_back AND a.Date GROUP BY 1, 2")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多