我正在使用 geonames 包来请求国家/地区名称,我可以手动执行此操作,但我不明白如何为表中的每一行进行 API 调用。
loc2$country = GNcountryCode(loc2$lon, loc2$lat)$countryCode
我的目的是创建一个新列“国家”,并填充相应的代码,但它似乎简单地将所有纬度和经度连接到一个请求中。
我对这个问题的基本性质表示歉意。我完全没有使用 R 的经验。我不知道如何使函数调用工作。
这是第 1 行:
loc2[1,]
latitudeE7 longitudeE7 accuracy activity source deviceTag
1 375800672 1268884670 22 ON_BICYCLE, ON_FOOT, IN_VEHICLE, UNKNOWN, 34, 30, 21, 13, 2014-01-24T10:12:51.748Z WIFI 1521681206
timestamp velocity altitude verticalAccuracy platformType serverTimestamp deviceTimestamp batteryCharging formFactor heading
1 2014-01-24T10:12:50.011Z NA NA NA <NA> <NA> <NA> NA <NA> NA
deviceDesignation lat lon day
1 <NA> 37.58007 126.8885 2014-01-24
背景:
官方要求我确定我在过去 10 年里访问过哪些国家以及停留时间。我经常旅行,经常以不同的方式前往/返回/前往另一个国家,甚至步行或骑自行车,因此我没有包含此信息的全面正式文件(如机票)。
我从未使用过 R,但经过一番阅读后,我认为分析我的 Google 位置历史记录是最简单的(尽管我经常启用飞行模式以延长电池寿命,所以即使这并不全面,但只是一个开始...... )
我有一个包含下载的 JSON 数据的数据表,并且通过仅选择唯一的日期将行数减少了 500 倍。 geonames 网站每小时允许 1000 次调用。
是的,我知道,一些(明智的)人会问,如果连我都不知道自己去过哪里,为什么我需要编译这些数据?我可以编造一个看似合理的虚构故事,但这本身已经成为一种痴迷。我已经 10 多年没有做过任何计算机工作了,所以我有点挣扎。
Geonames 国家/地区代码 API 不支持批量请求,因此您只能在每次调用中包含单个坐标对。你可以通过以下方式处理这个问题
mapply()
-- 定义一个接受 2 个参数(纬度、经度)并从响应中提取 countryCode
的函数,将其用作 mapply()
的第一个参数;传递 lat
和 lon
向量作为第二个和第三个参数,mapply
将循环遍历每个经纬度对,调用函数并返回带有结果的向量:
library(geonames)
# example locations:
loc2
#> lon lat
#> 1 -84.41688 77.88553
#> 2 -46.03540 -14.01990
#> 3 146.95480 59.73224
#> 4 -116.43957 47.22695
#> 5 60.64802 26.29448
loc2$country_gn <-
withr::with_options(
list(geonamesUsername=YOUR_GEONAMES_USERNAME),
mapply(\(lat, lon) GNcountryCode(lat, lon)$countryCode, loc2$lat, loc2$lon)
)
loc2
#> lon lat country_gn
#> 1 -84.41688 77.88553 CA
#> 2 -46.03540 -14.01990 BR
#> 3 146.95480 59.73224 RU
#> 4 -116.43957 47.22695 US
#> 5 60.64802 26.29448 IR
尽管您可以在没有任何外部 API 的情况下处理此问题:获取国家/地区多边形数据集(例如通过
giscoR
或 rnaturalearth
)并使用 sf
包提供的空间连接来查找与您的点位置的匹配项:
library(sf)
library(giscoR)
# CNTR_RG_20M_2016_4326 dataset
world <- gisco_countries
# for high(er) resolution dataset from 2024:
# world <- gisco_get_countries(year = "2024", resolution = "01")
# convert loc2 to a spatial data frame;
# spatial join with world[, "CNTR_ID"] to match each loc2 location to a country polygon;
# extract CNTR_ID column;
loc2$country_cisco <-
st_join(
st_as_sf(loc2, coords = c("lon", "lat"), crs = "WGS84"),
world[, "CNTR_ID"]
)$CNTR_ID
loc2
#> lon lat country_gn country_cisco
#> 1 -84.41688 77.88553 CA CA
#> 2 -46.03540 -14.01990 BR BR
#> 3 146.95480 59.73224 RU RU
#> 4 -116.43957 47.22695 US US
#> 5 60.64802 26.29448 IR IR
请注意,不同的地理空间数据集在标记某些区域时可能会采取不同的方法,当您必须处理克里米亚或北塞浦路斯等位置时需要考虑这一点。这也适用于反向地理编码 API。
示例地点:
set.seed(1)
loc2 <-
sf::st_sample(giscoR::gisco_countries, 5) |>
sf::st_coordinates() |>
`colnames<-`(c("lon", "lat")) |>
as.data.frame()
loc2 <- structure(list(lon = c(-84.4168839239306, -46.0353998519945,
146.954795316042, -116.439570855129, 60.6480190645839), lat = c(77.8855269367845,
-14.0199015626225, 59.7322442944768, 47.226945417709, 26.2944803596838
)), class = "data.frame", row.names = c(NA, -5L))
创建于 2024-10-09,使用 reprex v2.1.1