R Weather Underground — как использовать долготу и широту, чтобы получить ближайшую станцию аэропорта?

#json #r #weather #weather-api

#json #r #Погода #погода-api

Вопрос:

Как я могу найти ближайшую станцию аэропорта, используя долготу и широту?

Например, у меня есть это хранилище данных json в моей БД,

  "location" : {
    "long" : "Devon, 8 Market Road, Plympton, Plymouth PL7 1QW, United Kingdom",
    "street_number" : "",
    "route" : "Market Road",
    "locality" : "Plymouth",
    "administrative_area_level_1" : "England",
    "country" : "United Kingdom",
    "postal_code" : "PL7 1QW",
    "lat" : "50.38693379999999",
    "lng" : "-4.0598999999999705"
}
  

И я знаю, что это моя местность Plymouth , поэтому я буду запрашивать данные станций у Weather Underground по этому URL-адресу ниже:

http://api.wunderground.com/api /[MY-API-CODE]/geolookup/conditions/q/UK/Plymouth.json

Вот как я это делаю:

 locality <- 'Plymouth'

pullUrl <- paste(apiUrl, 'geolookup/conditions/q/UK/', locality, '.json', sep='')

# Reading in as raw lines from the web service.
conn <- url(pullUrl)
rawData <- readLines(conn, n=-1L, ok=TRUE)

# Convert to a JSON.
geoData <- fromJSON(paste(rawData, collapse=""))

# Get the station data in location only.
# Turn the result into a data frame.
stationsDF <- as.data.frame(geoData$location$nearby_weather_stations$airport$station)
  

Итак, я получаю 3 станции ниже:

       city state        country icao         lat         lon
1 Plymouth       United Kingdom EGDB 50.35491562 -4.12105608
2   Exeter                   UK EGTE 50.73714066 -3.40577006
3 Culdrose                   UK EGDR 50.08427429 -5.25711393
  

Но моя проблема в том, как я могу гарантировать, что я получу EGDB вместо EGTE или EGDR — потому что Плимптон ближе к Плимуту?

Итак, могу ли я использовать широту и lng ниже в моей базе данных, чтобы определить, какая станция является ближайшей?

 "lat" : "50.38693379999999",
"lng" : "-4.0598999999999705"
  

Итак, как я могу узнать, что широта и спг, указанные выше, должны EGDB 50.35491562 -4.12105608 соответствовать?

Есть идеи?

Редактировать:

 stationsDF <- as.data.frame(geoData$location$nearby_weather_stations$airport$station, stringsAsFactors=FALSE)
df <- setDT(stationsDF)
loc <- c(lat = "50.38693379999999", lng = "-4.0598999999999705")
dists <- geosphere::distHaversine(as.numeric(loc[c('lng', 'lat')]), df[, c('lon', 'lat')])
  

Ошибка:

 Error in .pointsToMatrix(p2) * toRad : 
  non-numeric argument to binary operator
In addition: Warning message:
In .pointsToMatrix(p2) : NAs introduced by coercion
  

РЕДАКТИРОВАТЬ 2:

 stationsDF <- as.data.frame(geoData$location$nearby_weather_stations$airport$station, stringsAsFactors=FALSE)
dput(stationsDF)
  

Вывод:

 structure(list(city = c("Plymouth", "Exeter", "Culdrose"), state = c("", 
"", ""), country = c("United Kingdom", "UK", "UK"), icao = c("EGDB", 
"EGTE", "EGDR"), lat = c("50.35491562", "50.73714066", "50.08427429"
), lon = c("-4.12105608", "-3.40577006", "-5.25711393")), .Names = c("city", 
"state", "country", "icao", "lat", "lon"), class = "data.frame", row.names = c(NA, 
-3L))
  

РЕДАКТИРОВАТЬ 3:

В то время как:

 str(stationsDF)
  

Вывод:

 'data.frame':   3 obs. of  6 variables:
 $ city   : chr  "Plymouth" "Exeter" "Culdrose"
 $ state  : chr  "" "" ""
 $ country: chr  "United Kingdom" "UK" "UK"
 $ icao   : chr  "EGDB" "EGTE" "EGDR"
 $ lat    : chr  "50.35491562" "50.73714066" "50.08427429"
 $ lon    : chr  "-4.12105608" "-3.40577006" "-5.25711393"
  

Комментарии:

1. geosphere::distHaversine

2. @alistaire как мне использовать это в моем случае? что сравнивать с чем?

Ответ №1:

Если у вас уже есть данные, скажем

 df <- read.table(text = 'city state        country icao         lat         lon
                   1 Plymouth     "United Kingdom" EGDB 50.35491562 -4.12105608
                   2   Exeter                   UK EGTE 50.73714066 -3.40577006
                   3 Culdrose                   UK EGDR 50.08427429 -5.25711393', head = T)

loc <- c(lat = "50.38693379999999", lng = "-4.0598999999999705")
  

Затем вы можете использовать geosphere::distHaversine для вычисления расстояний (по умолчанию в метрах) loc между и каждым наблюдением df :

 dists <- geosphere::distHaversine(as.numeric(loc[c('lng', 'lat')]), df[, c('lon', 'lat')])

dists
## [1]  5617.667 60493.398 91661.079
  

С which.min помощью вы можете индексировать df , чтобы получить результат:

 df[which.min(dists), ]
##   city    state        country icao      lat       lon
## 1    1 Plymouth United Kingdom EGDB 50.35492 -4.121056
  

Комментарии:

1. data.table имеет свою собственную систему подмножеств, поэтому, если вы собираетесь конвертировать df , вам придется индексировать его как df[, c('lon', 'lat'), with = FALSE] или df[, .(lon, lat)] .

2. Это отлично работает для опубликованных вами данных, но, похоже, он считает, что значение долготы меньше -360, которое он не может обработать.

3. Можете ли вы отредактировать результаты str(df) или dput(df) ? Трудно диагностировать без тех же данных.

4. Посмотрите str(df) ; все ваши переменные — это строки, а не числа. При необходимости вы можете преобразовать с df[] <- lapply(df, type.convert, as.is = TRUE) помощью или вручную.

5. Теперь я получил правильный результат. спасибо за помощь! 🙂