2016-07-06 18 views
3

Ich habe einen Datenrahmen mit über 3000 Aufzeichnungen, die die Breiten- und Längenkoordinaten jeder Beobachtung enthalten. Ich möchte das Land und den Staat oder die Provinz von jedem Koordinatensystem erhalten.Wie extrahiert man die JSON-Ausgabe in den Dataframe?

Ich schein eine Teillösung zu haben, aber ich bin ein Neophyt mit R und verstehe nicht, wie man die Informationen aus der JSON-Ausgabe in einen Datenrahmen extrahiert, den ich an den ursprünglichen Datensatz binden kann.

Wie analysiere ich die verschachtelte Liste, die von fromJSON erstellt wurde, in ein data.frame? Insbesondere, mag ich den neuen Datenrahmen wie etwas aussehen:

Breite, Länge, Land, Staat (Spaltennamen)

Alternativ kann eine bessere Lösung für mein Problem der räumlichen Informationen zu erhalten sind geschätzt!

Hier ist mein Code:

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

Mögliche Duplikate von [JSON mit R parsen] (http://stackoverflow.com/questions/2061897/parse-json-with-r) – alistaire

+0

@alistaire Ich habe den Beitrag gelesen und entweder bekomme ich es nicht oder es löst mein Problem nicht! Sorry, wenn es das erste ist, aber wie gesagt, ich bin neu mit JSON-Ausgabe und Listen arbeiten. –

Antwort

4

Ich ziehe es für das Parsen von JSON in R. jsonlite verwenden

die verschachtelte JSON Liste zu analysieren, können Sie die fromJSON Anruf innerhalb eines lapply tun können.

jsonlite::fromJSON versucht, das Ergebnis für Sie zu vereinfachen. Da JSON jedoch für verschachtelte Datenstrukturen ausgelegt ist, wird häufig ein dat.frame von Listen zurückgegeben. Um also das gewünschte data.frame zu erhalten, müssen Sie wissen, welches Element der Liste Sie suchen und extrahieren.

Zum Beispiel

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 

Um die data.frame Sie einen weiteren lapply konstruieren können die Elemente zu extrahieren, die Sie wollen, und es dann ganz setzen entweder mit einem do.call(..., rbind) oder meine Vorlieben ist mit 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 

Alternativ können Sie die Google-API über library(googleway) (Disclaimer: Ich schrieb googleway) verwenden, um mehr Details zu jedem Breitengrad/Lon zu erfahren, um den Lat/Lons umzukodieren.

Dafür benötigen Sie einen gültigen Google-API-Schlüssel (die bis 2500 Anfragen pro Tag begrenzt ist, es sei denn, Sie zahlen)

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 

oder in ähnliche Weise durch library(ggmap), auch begrenzt durch 2.500 Limit von 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

Ich denke meine Frage ist unklar. Ich möchte eine Datenausgabe, die Lat, Long, Country, State oder Province enthält. –

+0

@KeithLarson - ok - Ich habe meine Antwort aktualisiert – SymbolixAU

+0

danke und ich sehe, wohin das geht, aber ich bin immer noch fest, weil Ihre Lösung mir vier Datensätze für jede ursprüngliche Beobachtung gibt. Ich versuche immer noch, den Kopf über "rbindlist" zu legen und wie er die Daten arrangiert. –

1

Diese JSON-Liste muss extrahiert werden. Sie haben wirklich nur ein Ergebnis von Ihrem ersten Koordinate:

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" 

Sie sollten apply die Koordinaten alle laufen verwendet haben one-by-one durch die fromJSON(coordinates2politics(.,.) Extraktion, da die Funktion nicht „vektorisiert“ erscheint.

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" 

Anscheinend werden Gegenstände in der Nähe der Grenze (wie San Diego County oder Chula Vista) mehrdeutige Ergebnisse geben.