Map/mapply 包含两个列表的所有可能组合
Map/mapply with all possible combinations of two lists
我刚开始使用 R 并申请,我正在尝试从网站下载一组 .csv 文件。
我想下载危地马拉 (GT)、萨尔瓦多 (SV) 和洪都拉斯 (HN) 这三个国家的 2004 年和 2005 年(作为示例;实际上我想要更多年)。
我可以 运行 按国家/地区执行以下操作:
years = c(2004, 2005)
Map(download.file, url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", years, "/DEUAGT%20S1%20", years, ".csv"),
destfile = paste0(raw_data, years, ".csv") )
这将使我获得 2004 年和 2005 年的危地马拉数据库,因为危地马拉基地由 URL 中的 "DEAUGT" 定义。洪都拉斯和 El Salvatorian 数据库分别是 "DEAUHN" 和 "DEAUSV"。
但是因为我正在努力学习,所以我想把所有的东西都放在“一个运行”中。所以我尝试了:
countries = c("GT", "HN", "SV")
years = c(2004, 2005, 2007, 2009:2019)
Map(possibly(download.file, otherwise = NA), url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", years, "/DEUA", countries, "%20", years, ".csv"),
destfile = paste0(raw_data, countries, years,".csv"))
但是我没有下载我想要的 6 个文件(三个国家,两年),而是下载了 2 个文件。
我在这里找到的各种帖子都注意到了,在 RStudio 社区中注意到 Map/mapply 没有 运行 通过列表 "countries"
和 "years"
的所有可能组合,而是逐点(或类似的东西)。
我在不同的设置中找到了各种建议,但 none 特别容易,而且有些事情告诉我有一个简单的解决方案。使用 expand.grid
创建数据框而不是列表列表。
您可以使用以下解决方案。如果我们使用 purrr::walk2
代替 purrr::map2
会更好,因为我们调用 download.file
是为了它的副作用,所以 walk2
是更好的选择:
library(purrr)
# First we create a data frame of all combinations of countries and years
comb <- expand.grid(countries, years)
# Then I wrap `download.file` with possibly for error handling
poss_download <- possibly(download.file, otherwise = NA)
# Then I apply our function on every combination of countries and years
# in a row-wise operation
walk2(comb$Var1, comb$Var2, ~ {
url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", .y, "/DEUA", .x, "%20", .y, ".csv")
destfile = paste0(raw_data, .x, .y,".csv")
poss_download(url, destfile)
})
这是这个问题的基本 R 解决方案。
- 而不是
paste0
我使用了 sprintf
函数,根据文档“returns 包含文本和变量值的格式化组合的字符向量”。我将 %d
用于 integer/numeric 值(2 次代表年份),使用 %s
代表字符串(一次用于国家),应该注意的是我们必须提供尽可能多的变量,以便它们并入它们的位置以形成长度为 one 的单个字符串
- 然后我用
tryCatch
代替 purrr::possibly
来处理可能的错误
- 最后我使用
mapply
或Map
同时迭代两个向量url
和destfile
comb <- expand.grid(countries, years)
url <- sprintf("https://www.colef.mx/emif/datasets/basesdeDatos/sur/%d/DEUA%s%d.csv", comb$Var2, comb$Var1, comb$Var2)
destfile = paste0(raw_data, comb$Var1, comb$Var2,".csv")
mapply(function(x, y) {
tryCatch(download.file(url, destfile),
error = function(e) {
NA
})
}, url, destfile)
我刚开始使用 R 并申请,我正在尝试从网站下载一组 .csv 文件。
我想下载危地马拉 (GT)、萨尔瓦多 (SV) 和洪都拉斯 (HN) 这三个国家的 2004 年和 2005 年(作为示例;实际上我想要更多年)。
我可以 运行 按国家/地区执行以下操作:
years = c(2004, 2005)
Map(download.file, url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", years, "/DEUAGT%20S1%20", years, ".csv"),
destfile = paste0(raw_data, years, ".csv") )
这将使我获得 2004 年和 2005 年的危地马拉数据库,因为危地马拉基地由 URL 中的 "DEAUGT" 定义。洪都拉斯和 El Salvatorian 数据库分别是 "DEAUHN" 和 "DEAUSV"。
但是因为我正在努力学习,所以我想把所有的东西都放在“一个运行”中。所以我尝试了:
countries = c("GT", "HN", "SV")
years = c(2004, 2005, 2007, 2009:2019)
Map(possibly(download.file, otherwise = NA), url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", years, "/DEUA", countries, "%20", years, ".csv"),
destfile = paste0(raw_data, countries, years,".csv"))
但是我没有下载我想要的 6 个文件(三个国家,两年),而是下载了 2 个文件。
我在这里找到的各种帖子都注意到了,在 RStudio 社区中注意到 Map/mapply 没有 运行 通过列表 "countries"
和 "years"
的所有可能组合,而是逐点(或类似的东西)。
我在不同的设置中找到了各种建议,但 none 特别容易,而且有些事情告诉我有一个简单的解决方案。使用 expand.grid
创建数据框而不是列表列表。
您可以使用以下解决方案。如果我们使用 purrr::walk2
代替 purrr::map2
会更好,因为我们调用 download.file
是为了它的副作用,所以 walk2
是更好的选择:
library(purrr)
# First we create a data frame of all combinations of countries and years
comb <- expand.grid(countries, years)
# Then I wrap `download.file` with possibly for error handling
poss_download <- possibly(download.file, otherwise = NA)
# Then I apply our function on every combination of countries and years
# in a row-wise operation
walk2(comb$Var1, comb$Var2, ~ {
url = paste0("https://www.colef.mx/emif/datasets/basesdeDatos/sur/", .y, "/DEUA", .x, "%20", .y, ".csv")
destfile = paste0(raw_data, .x, .y,".csv")
poss_download(url, destfile)
})
这是这个问题的基本 R 解决方案。
- 而不是
paste0
我使用了sprintf
函数,根据文档“returns 包含文本和变量值的格式化组合的字符向量”。我将%d
用于 integer/numeric 值(2 次代表年份),使用%s
代表字符串(一次用于国家),应该注意的是我们必须提供尽可能多的变量,以便它们并入它们的位置以形成长度为 one 的单个字符串
- 然后我用
tryCatch
代替purrr::possibly
来处理可能的错误 - 最后我使用
mapply
或Map
同时迭代两个向量url
和destfile
comb <- expand.grid(countries, years)
url <- sprintf("https://www.colef.mx/emif/datasets/basesdeDatos/sur/%d/DEUA%s%d.csv", comb$Var2, comb$Var1, comb$Var2)
destfile = paste0(raw_data, comb$Var1, comb$Var2,".csv")
mapply(function(x, y) {
tryCatch(download.file(url, destfile),
error = function(e) {
NA
})
}, url, destfile)