【问题标题】:Translating a `for loop` into purrr using `map` function in r使用 r 中的 `map` 函数将`for loop` 转换为 purrr
【发布时间】:2021-08-17 01:17:41
【问题描述】:

我需要从 NASA 的 POWER(全球能源资源预测)下载天气数据。 nasapower 包是为使用 R 进行数据检索而开发的包。我需要下载许多位置(纬度、经度坐标)。为此,我尝试了一个包含三个位置的简单循环作为可重现的示例。

library(nasapower)

data1 <- read.csv(text = "
location,long,lat
loc1, -56.547, -14.2427
loc2, -57.547, -15.2427
loc3, -58.547, -16.2427")

i=1
all.weather <- data.frame()
for (i in seq_along(1:nrow(data1))) {

        weather.data <- get_power(community = "AG",
                          lonlat = c(data1$long[i],data1$lat[i]),
                          dates = c("2015-01-01", "2015-01-10"),
                          temporal_average = "DAILY",
                          pars = c("T2M_MAX"))
        
        all.weather <-rbind(all.weather, weather.data)
}

这很完美。问题是我试图使用purrr::map 来模仿这个,因为我想在tidyverse 中有一个替代方案。这是我所做的,但它不起作用:

library(dplyr)
library(purrr)

all.weather <- data1 %>%
    group_by(location) %>%
    map(get_power(community = "AG",
                lonlat = c(long, lat),
                dates = c("2015-01-01", "2015-01-10"),
                temporal_average = "DAILY",
                site_elevation = NULL,
                pars = c("T2M_MAX")))

我收到以下错误:

Error in isFALSE(length(lonlat != 2)) : object 'long' not found

关于如何使用purrr 运行它的任何提示?

【问题讨论】:

  • get_power 符合 tidy eval 吗?如果没有,您可能必须指定 data1$long, data1$lat...

标签: r loops for-loop tidyverse purrr


【解决方案1】:

要使您的代码正常工作,请使用purrr::pmap 而不是map,如下所示:

  1. map 用于一个参数函数,map2 用于两个参数函数,pmap 是最通用的函数,允许具有两个以上参数的函数。

  2. pmap 将遍历 df 的行。由于您的 df 有 3 列,因此即使未使用第一个参数 location,也会将 3 个参数传递给函数。要完成这项工作并使用列名,您必须通过 function(location, long, lat) 指定函数和参数名称

library(nasapower)

data1 <- read.csv(text = "
location,long,lat
loc1, -56.547, -14.2427
loc2, -57.547, -15.2427
loc3, -58.547, -16.2427")

library(dplyr)
library(purrr)

all.weather <- data1 %>%
  pmap(function(location, long, lat) get_power(community = "AG",
                                               lonlat = c(long, lat),
                                               dates = c("2015-01-01", "2015-01-10"),
                                               temporal_average = "DAILY",
                                               site_elevation = NULL,
                                               pars = c("T2M_MAX"))) %>% 
  # Name list with locations
  setNames(data1$location) %>% 
  # Add location names as identifiers
  bind_rows(.id = "location")

head(all.weather)
#> NASA/POWER SRB/FLASHFlux/MERRA2/GEOS 5.12.4 (FP-IT) 0.5 x 0.5 Degree Daily Averaged Data  
#>  Dates (month/day/year): 01/01/2015 through 01/10/2015  
#>  Location: Latitude  -14.2427   Longitude -56.547  
#>  Elevation from MERRA-2: Average for 1/2x1/2 degree lat/lon region = 379.25 meters   Site = na  
#>  Climate zone: na (reference Briggs et al: http://www.energycodes.gov)  
#>  Value for missing model data cannot be computed or out of model availability range: NA  
#>  
#>  Parameters: 
#>  T2M_MAX MERRA2 1/2x1/2 Maximum Temperature at 2 Meters (C)  
#>  
#> # A tibble: 6 x 9
#>   location   LON   LAT  YEAR    MM    DD   DOY YYYYMMDD   T2M_MAX
#>   <chr>    <dbl> <dbl> <dbl> <int> <int> <int> <date>       <dbl>
#> 1 loc1     -56.5 -14.2  2015     1     1     1 2015-01-01    29.9
#> 2 loc1     -56.5 -14.2  2015     1     2     2 2015-01-02    30.1
#> 3 loc1     -56.5 -14.2  2015     1     3     3 2015-01-03    27.3
#> 4 loc1     -56.5 -14.2  2015     1     4     4 2015-01-04    28.7
#> 5 loc1     -56.5 -14.2  2015     1     5     5 2015-01-05    30  
#> 6 loc1     -56.5 -14.2  2015     1     6     6 2015-01-06    28.7

【讨论】:

  • 一个问题是为什么我的 df 中的位置名称没有被拉到输出中。有什么方法可以保存输出中的位置名称吗?
  • 嗨@GiuseppePetri。我只是对我的代码进行了一个小编辑,以将带有位置名称的列添加到最终输出中
  • 太棒了!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多