【问题标题】:How to add progress bar inside dplyr chain in R如何在 R 中的 dplyr 链中添加进度条
【发布时间】:2017-03-10 18:31:47
【问题描述】:

我喜欢 dplyr 的“progress_estimated”功能,但我不知道如何让进度条在 dplyr 链中工作。我在这里底部放了一个可重现的示例代码。

我有一个相当大的 data.frame,像这样:

                cdatetime latitude longitude   
1 2013-01-11 06:40:00 CST 49.74697 -93.30951
2 2013-01-12 15:55:00 CST 49.74697 -93.30951 
3 2013-01-07 20:30:00 CST 49.74697 -93.30951 

我想使用库计算每个日期的日出时间

library(dplyr)
library(StreamMetabolism)

我可以让 dplyr 的 progress_estimated 条在循环中工作,例如:

丑陋的循环(有效)

p <- progress_estimated(nrow(test))

for (i in 1:nrow(test)){
  p$tick()$print()
  datetime = as.POSIXct(substr(test$cdatetime[i], 1, 20), tz = "CST6CDT")
  test$sunrise[i] <- sunrise.set(test$latitude[i], test$longitude[i], datetime, "CST6CDT", num.days = 1)[1,1]
}

但是如何将它嵌套在我的函数中,这样我就可以避免使用循环?

喜欢使用:

SunriseSet <- function(dataframe, timezone){
  dataframe %>% 
    rowwise() %>% 
    mutate(# calculate the date-time using the correct timezone
      datetime = as.POSIXct(substr(cdatetime, 1, 20), tz = timezone),
      # Get the time of sunrise and sunset on this day, at the county midpoint
      sunrise = sunrise.set(latitude, longitude, datetime, timezone, num.days = 1)[1,1])
}

如何在这里获得进度条?

test2 <- SunriseSet(test, "CST6CDT")

以下是一些示例数据:

test <- data.frame(cdatetime = rep("2013-01-11 06:40:00", 300),
                   latitude = seq(49.74697, 50.04695, 0.001),
                   longitude = seq(-93.30951, -93.27960, 0.0001))

【问题讨论】:

  • 我觉得进度条应该也可以分组使用。例如,如果您将日期分组,则在每个组之间进行变异。

标签: r progress-bar dplyr


【解决方案1】:

与其使用rowwise(),不如尝试将purrr 中的map* 函数与progress_estimated() 配对。此答案遵循https://rud.is/b/2017/03/27/all-in-on-r%E2%81%B4-progress-bars-on-first-post/ 的方法。

首先,将您的函数包装在另一个更新进度条的函数中:

SunriseSet <- function(lat, long, date, timezone, num.days, .pb = NULL) {
  if (.pb$i < .pb$n) .pb$tick()$print()
  sunrise.set(lat, long, date, timezone, num.days)
}

然后,使用pmappmap_df 遍历您的输入(将输出绑定到数据框):

library(purrr)
pb <- progress_estimated(nrow(test), 0)
test2 <- test %>% 
  mutate(
    sunrise = pmap_df(
      list(
        lat = latitude, 
        long = longitude,
        date = as.character(cdatetime)
      ),
      SunriseSet,
      timezone = "CST6CDT", num.days = 1, .pb = pb
    )$sunrise
  )

【讨论】:

  • 行得通!我会看看如何将日落添加到输出数据帧中......谢谢!
【解决方案2】:

我不太喜欢我的解决方案,但它确实有效。

print_tick_function <- function(x, p) {
  p$tick()$print()
  data.frame(x)
}

SunriseSet <- function(dataframe, timezone){
  p <- progress_estimated(nrow(dataframe))
  dataframe %>% 
    rowwise() %>% 
    do(print_tick_function(.,p)) %>%
    mutate(
      datetime = as.POSIXct(substr(cdatetime, 1, 20), tz = timezone),
      sunrise = sunrise.set(latitude, longitude, datetime, timezone, num.days = 1)[1,1]
    )
}
test2 <- SunriseSet(test, "CST6CDT")

【讨论】:

  • 谢谢@nehiljain,关于do(),我还有很多东西要学。我在更大的 data.frame 上进行了尝试,但进度条不准确 - 进度达到 100%,但几分钟后该功能仍在运行。
  • @Nova 我有同样的经历,在实际计算完成之前进度达到 100%
猜你喜欢
  • 2021-10-06
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 2016-11-06
  • 1970-01-01
  • 2016-10-07
  • 1970-01-01
相关资源
最近更新 更多