2016-07-06 3 views
3

У меня есть кадр данных с более чем 3000 записей, которые включают координаты широты и долготы каждого наблюдения. Я хотел бы получить страну и штат или провинцию от каждого набора координат.Как извлечь вывод JSON в dataframe?

У меня есть частичное решение, но я неофит с R и не понимаю, как извлечь информацию из вывода JSON в кадр данных, который я могу привязать к исходному набору данных.

Как разобрать вложенный список, созданный fromJSON в data.frame? частности, я хотел бы новые данные рамки, чтобы выглядеть примерно так:

широта, долгота, Страна, государственные (имена столбцов)

В качестве альтернативы, лучшим решением моей проблемы получения пространственной информации оценили!

Вот мой код:

library(RDSTK) 
library(httr) 
library(rjson) 
Coords <- structure(list(Latitude = c(43.30528, 46.08333, 32.58333, 46.25833, 45.75, 46.25, 45.58333, 45.58333, 44.08333, 45.75), 
         Lontitude = c(-79.80306, -82.41667, -117.08333, -123.975, -85.75, -123.91667, -86.75, -86.75, -76.58333, -85.25 
             )), .Names = c("Latitude", "Longitude"), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L,9L, 10L), class = "data.frame") 

json_file <- fromJSON(coordinates2politics(Coords$Latitude, Coords$Longitude)) 
+1

Возможный дубликат [Parse JSON with R] (http://stackoverflow.com/questions/2061897/parse-json-with-r) – alistaire

+0

@alistaire Я прочитал сообщение, и либо я его не получаю, либо он не решает мою проблему! Извините, если он первый, но, как я уже сказал, я новичок в работе с выводами и списками JSON. –

ответ

4

Я предпочитаю использовать jsonlite для разбора JSON в R.

Для разбора вложенного списка JSON, вы можете сделать вызов fromJSON внутри lapply.

jsonlite::fromJSON пытается упростить результат для вас. Но поскольку JSON предназначен для обработки вложенных структур данных, вы часто возвращаете список данных. Таким образом, чтобы получить data.frame, вы должны знать, какой элемент списка вы хотите, и извлечь его.

Например

library(RDSTK) 
library(jsonlite) 

js <- coordinates2politics(Coords$Latitude, Coords$Longitude) 
lst <- lapply(js, jsonlite::fromJSON) 

lst[[1]]$politics 
#   type friendly_type      name code 
# 1  admin2  country      Canada can 
# 2  admin4   state     Ontario ca08 
# 3 constituency constituency   Hamilton Centre 35031 
# 4 constituency constituency     Burlington 35010 
# 5 constituency constituency Hamilton East-Stoney Creek 35032 

Чтобы получить data.frame, вы можете построить еще lapply извлечь элементы, которые вы хотите, а затем положить его в целом или с do.call(..., rbind), или мои предпочтения есть с data.table::rbindlist(...)

lst_result <- lapply(lst, function(x){ 
    df <- x$politics[[1]] 
    df$lat <- x$location$latitude 
    df$lon <- x$location$longitude 
    return(df) 
}) 

data.table::rbindlist(lst_result) 

#   type friendly_type         name     code  lat  lon 
# 1:  admin2  country        Canada     can 43.30528 -79.80306 
# 2:  admin4   state        Ontario     ca08 43.30528 -79.80306 
# 3: constituency constituency      Hamilton Centre     35031 43.30528 -79.80306 
# 4: constituency constituency       Burlington     35010 43.30528 -79.80306 
# 5: constituency constituency   Hamilton East-Stoney Creek     35032 43.30528 -79.80306 
# 6:  admin2  country        Canada     can 46.08333 -82.41667 
# 7:  admin4   state        Ontario     ca08 46.08333 -82.41667 

В качестве альтернативы, чтобы получить более подробную информацию о каждом лат/лоне, вы можете использовать API Google через library(googleway) (Отказ от ответственности: я написал googleway), чтобы отменить геокодирование lat/lons.

Для этого вам потребуется действующий ключ Google API (который ограничен до 2500 запросов в день, если вы не платите)

library(googleway) 

key <- "your_api_key" 

lst <- apply(Coords, 1, function(x){ 
    google_reverse_geocode(location = c(x["Latitude"], x["Longitude"]), 
          key = key) 
}) 

lst[[1]]$results$address_components 
# [[1]] 
#        long_name       short_name         types 
# 1 Burlington Bay James N. Allan Skyway Burlington Bay James N. Allan Skyway         route 
# 2       Burlington       Burlington     locality, political 
# 3   Halton Regional Municipality   Halton Regional Municipality administrative_area_level_2, political 
# 4        Ontario         ON administrative_area_level_1, political 
# 5        Canada         CA      country, political 
# 6         L7S         L7S  postal_code, postal_code_prefix 

Или так же через library(ggmap), также ограничена 2500 предела Google.

library(ggmap) 

apply(Coords, 1, function(x){ 
    revgeocode(c(x["Longitude"], x["Latitude"])) 
}) 

# 1 
# "Burlington Bay James N. Allan Skyway, Burlington, ON L7S, Canada" 
# 2 
# "308 Brennan Harbour Rd, Spanish, ON P0P 2A0, Canada" 
# 3 
# "724 Harris Ave, San Diego, CA 92154, USA" 
# 4 
# "30 Cherry St, Chinook, WA 98614, USA" 
# 5 
# "St James Township, MI, USA" 
# 6 
# "US-101, Chinook, WA 98614, USA" 
# 7 
# "2413 II Rd, Garden, MI 49835, USA" 
# 8 
# "2413 II Rd, Garden, MI 49835, USA" 
# 9 
# "8925 S Shore Rd, Stella, ON K0H 2S0, Canada" 
# 10 
# "Charlevoix County, MI, USA" 
+0

Я думаю, мой вопрос непонятен. Я хотел бы получить вывод dataframe, который включает в себя: Lat, Long, Country, State или Province. –

+0

@KeithLarson - ok - я обновил свой ответ – SymbolixAU

+0

спасибо, и я вижу, где это происходит, но я все еще застреваю, потому что ваше решение дает мне четыре записи для каждого оригинального наблюдения. Все еще пытаюсь обернуть голову вокруг «rbindlist» и как он решает упорядочить данные. –

1

Этот json-список необходимо извлечь. Вы действительно только результат от вашего первой координаты:

sapply(json_file[[1]]$politics, "[[", 'name')[ # now pick correct names with logical 
     sapply(json_file[[1]]$politics, "[[", 'friendly_type') %in% c("country","state") ] 
[1] "Canada" "Ontario" 

Вы должны были использовать apply для выполнения всех координат один за другим через fromJSON(coordinates2politics(.,.) экстракции, так как функция, кажется, не быть «Векторизованным».

res=apply(Coords, 1, function(x) {fromJSON(coordinates2politics(x['Latitude'], 
                   x['Longitude']))}) 
sapply(res, function(x) sapply(x[[1]]$politics, "[[", 'name')[ 
          sapply(x[[1]]$politics, "[[", 'friendly_type') %in% 
                   c("country","state")]) 
$`1` 
[1] "Canada" "Ontario" 

$`2` 
[1] "Canada" "Ontario" 

$`3` 
[1] "United States" "California" "Mexico"  "California" 

$`4` 
[1] "United States" 

$`5` 
[1] "United States" "Michigan"  

$`6` 
[1] "United States" "Washington" 

$`7` 
[1] "United States" "Michigan"  

$`8` 
[1] "United States" "Michigan"  

$`9` 
[1] "Canada" "Ontario" 

$`10` 
[1] "United States" "Michigan" 

По-видимому, предметы вблизи границы (например, округ Сан-Диего или Чула Виста) дадут неоднозначные результаты.

Смежные вопросы