2017-07-25 90 views
2

我已經從google_reverse_code API下載地址列表,但是獲取經緯度信息的地方列表,因爲我在R中很新。我不知道如何提取有用的信息。所有下載數據庫的代碼都在問題的底部。從R嵌套列表中提取數據

列表的結構一般是這樣的。

`$ 60 :List of 1 
..$ results:'data.frame': 1 obs. of 5 variables: 
.. ..$ address_components:List of 1 
.. .. ..$ :'data.frame': 8 obs. of 3 variables: 
.. .. .. ..$ long_name : chr [1:8] "119" "Avenida Diego Díaz de Berlanga" 
"Jardines de Anahuac 2do Sector" "San Nicolás de los Garza" ... 
.. .. .. ..$ short_name: chr [1:8] "119" "Avenida Diego Díaz de Berlanga" 
"Jardines de Anahuac 2do Sector" "San Nicolás de los Garza" ... 
.. .. .. ..$ types  :List of 8 
.. .. .. .. ..$ : chr "street_number" 
.. .. .. .. ..$ : chr "route" 
.. .. .. .. ..$ : chr [1:3] "political" "sublocality" "sublocality_level_1" 
.. .. .. .. ..$ : chr [1:2] "locality" "political" 
.. .. .. .. ..$ : chr [1:2] "administrative_area_level_2" "political" 
.. .. .. .. ..$ : chr [1:2] "administrative_area_level_1" "political" 
.. .. .. .. ..$ : chr [1:2] "country" "political" 
.. .. .. .. ..$ : chr "postal_code" 
.. ..$ formatted_address : chr "Avenida Diego Díaz de Berlanga 119, Jardines 
de Anahuac 2do Sector, 66444 San Nicolás de los Garza, N.L., Mexico" 
.. ..$ geometry   :'data.frame': 1 obs. of 3 variables: 
.. .. ..$ location  :'data.frame': 1 obs. of 2 variables: 
.. .. .. ..$ lat: num 25.7 
.. .. .. ..$ lng: num -100 
.. .. ..$ location_type: chr "ROOFTOP" 
.. .. ..$ viewport  :'data.frame': 1 obs. of 2 variables: 
.. .. .. ..$ northeast:'data.frame': 1 obs. of 2 variables: 
.. .. .. .. ..$ lat: num 25.7 
.. .. .. .. ..$ lng: num -100 
.. .. .. ..$ southwest:'data.frame': 1 obs. of 2 variables: 
.. .. .. .. ..$ lat: num 25.7 
.. .. .. .. ..$ lng: num -100 
.. ..$ place_id   : chr "ChIJRY_wPdqUYoYRTJetT6AJETA" 
.. ..$ types    :List of 1 
.. .. ..$ : chr "street_address" 

我需要這些信息作爲數據框來執行我的分析。該信息具體爲C(緯度,經度,的formatted_address,place_id)

我寫的代碼是這樣的:

prueba <- sapply(direccion1, function(x){ 
uno <- unlist(x[[1]]) 
}) 

pureba2 < - data.frame(prueba)

我得到的以下錯誤:Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, : arguments imply differing number of rows: 40, 32, 37, 44, 36, 0, 41, 28, 39, 47, 43, 35, 48 其他代碼不起作用。

用於下載包含經度和緯度的數據的代碼如下。

# CRE FILES 
library(easypackages) 
my_packages <- c("ggmap","maps","mapdata","rlist","readr", "tidyverse", 
"lubridate", "stringr", "rebus", "stringi", "purrr", "geosphere", "XML", 
"RCurl", "xml2") 
libraries(my_packages) 

# Set link to website 

link1 <- 
("https://publicacionexterna.azurewebsites.net/publicaciones/prices") 

# Get data from webpage 

data_prices <- getURL(link1) 

# Parse XML data 

xmlfile <- xmlParse(data_prices) 

# Get place nodes 

places <- getNodeSet(xmlfile, "//place") 

# Get values for each place 

values <- lapply(places, function(x){ 

# Get current place id 

p_id <- xmlAttrs(x) 

# Get values for each gas type for current place 

newrows <- lapply(xmlChildren(x), function(y){ 

    # Get type and update time 

    attrs <- xmlAttrs(y) 

    # Get price value 

    price <- xmlValue(y) 

names(price) <- "price" 

# Return values 

return(c(p_id, attrs, price) 
     ) 
    }) 

    # Combine rows to single list 

    newrows <- do.call(rbind, newrows) 

    # Return rows 

    return(newrows) 


    }) 

    # Combine all values into a single dataframe 

    datosDePrecios <- as.data.frame(do.call(rbind, values), stringsAsFactors = 
    FALSE) 

    # Re-set row names for dataframe 

    row.names(datosDePrecios) <- c(1:nrow(datosDePrecios)) 

    # Set link to website to the places file 

    link2 <- 
    ("https://publicacionexterna.azurewebsites.net/publicaciones/places") 


    data_places <- read_xml(link2) 

    datos_id <- data_places %>% 
    xml_find_all("//place") %>% 
    xml_attr("place_id") 

datos_name <- data_places %>% 
    xml_find_all("//name") %>% 
    xml_text("name") 

datos_brand <- data_places %>% 
    xml_find_all("//brand") %>% 
    xml_text("brand") 

datos_cre_id <- data_places %>% 
    xml_find_all("//cre_id") %>% 
    xml_text("cre_id") 

datos_category <- data_places %>% 
    xml_find_all("//category") %>% 
    xml_text("category") 

datos_adress_street <- data_places %>% 
    xml_find_all("//address_street") %>% 
    xml_text("adress_street") 

datos_longitud <- data_places %>% 
    xml_find_all("//x") %>% 
    xml_text("x") 

datos_latitud <- data_places %>% 
    xml_find_all("//y") %>% 
    xml_text("y") 

datosDeLugares <- data.frame(datos_id, datos_name, 
        datos_brand, datos_cre_id, 
        datos_category, datos_adress_street, 
        datos_latitud, datos_longitud) 

colnames(datosDeLugares) <- c("place_id", "name", "brand","cre_id", 
"category", "adress_street", "Latitude", "Longitude") 


rm(data_prices,places,values,xmlfile,data_places, datos_adress_street, 
datos_brand, datos_category, datos_cre_id, datos_id, datos_name, 
datos_longitud, datos_latitud) 

rm(results, results2) 

獲取地址信息的代碼如下。

datosDePrecios <- datosDePrecios %>% 
    data.frame(datosDePrecios) %>% 
    mutate(place_id = as.numeric(place_id)) 

datosDeLugares <- datosDeLugares %>% 
    data.frame(datosDeLugares) %>% 
    mutate(place_id = as.numeric(place_id)) 


baseGeneral <- inner_join(datosDeLugares, datosDePrecios, by = "place_id") 


baseGeneral <- baseGeneral %>% 
    select(Latitude, Longitude, place_id) %>% 
    mutate(Latitude = as.numeric(as.character(Latitude))) %>% 
    mutate(Longitude = as.numeric(as.character(Longitude))) 

baseGeneral <- baseGeneral[1:100,] 

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

謝謝你的幫忙。 :)

+0

你可能想嘗試tidyr :: UNNEST()https://rdrr.io/cran/tidyr/man/unnest.html –

+0

我認爲tidyr只適用於數據框類數據。我擁有的是一個列表。你知道一些使用列表格式工作的方法嗎?謝謝您的回答。 –

+0

您是否可以包含下載該數據的代碼,以便其他人可以複製您擁有的對象? – moman822

回答

1

您可以使用[[符號,或$

提取列表信息。如果我參加?google_reverse_geocode給出的例子中得到一個結果

library(googleway) 

res <- google_reverse_geocode(location = c(-37.81659, 144.9841), 
           result_type = c("street_address"), 
           location_type = "rooftop", 
           key = key) 

的經/緯度信息是res$results$geometry$location

格式化地址在res$results$formatted_address

而且place_id是res$results$place_id

所以,你可以創建你data.frame從這些元素

data.frame(
    lat = res$results$geometry$location$lat, 
    lon = res$results$geometry$location$lng, 
    formatted_address = res$results$formatted_address, 
    place_id = res$results$place_id 
) 

如果有結果的多個列表,那麼這個過程是相似的,但你需要將其包裝在一個*apply函數(或任何您喜歡的循環機制)中

## a list of locations 
locations <- list(c(-37.81659, 144.9841), c(-37.81827, 144.9671)) 

## generating the reverse geocode for each location 
lst_res <- lapply(locations, function(x){ 
    google_reverse_geocode(location = x, key = key) 
}) 

這裏,lst_res都是從地理編碼功能的結果列表,這樣你就可以遍歷它來提取相關部分

## now we can extract the information 
lst_df <- lapply(lst_res, function(x){ 
    data.frame(
    lat = x[['results']][['geometry']][['location']][['lat']], 
    lon = x[['results']][['geometry']][['location']][['lng']], 
    formatted_address = x[['results']][['formatted_address']], 
    place_id = x[['results']][['place_id']] 
) 
}) 

這裏,lst_df是data.frames的列表。如果你想將它們合成爲一個單一的data.frame可以

df <- do.call(rbind, lst_df) 

## et voila! 
head(df) 
# lat  lon 
# 1 -37.81647 144.9841 
# 2 -37.81659 144.9841 
# 3 -37.81300 144.9850 
# 4 -37.81363 144.9631 
# 5 -37.81614 144.9805 
# 6 -37.81005 144.9281 
# formatted_address 
# 1 Jolimont Station, 175 Wellington Parade, East Melbourne VIC 3002, Austalia 
# 2  Jolimont Station, Wellington Cres, East Melbourne VIC 3002, Australia 
# 3           East Melbourne VIC 3002, Australia 
# 4             Melbourne VIC, Australia 
# 5           East Melbourne VIC 3002, Australia 
# 6             Melbourne, VIC, Australia 
# place_id 
# 1 ChIJSxAubOpC1moRqhRUnMoZV4M 
# 2 ChIJIdtrbupC1moRMPT0CXZWBB0 
# 3 ChIJz25SvMFC1moRAOiMIXVWBAU 
# 4 ChIJ90260rVG1moRkM2MIXVWBAQ 
# 5 ChIJG74w4Upd1moRsDQuRnhWBBw 
# 6 ChIJv_FYgkNd1moRpxLuRXZURFs 
+0

@SymolixAu。感謝您的回答,讓像我這樣的專家幫助像我這樣的新手非常有幫助。祝你有美好的一天。 :) –

1

我認爲你遇到的問題unlist()是默認的recursive=TRUE。所以它可能沒有列出你的數據框,並且列出你的數據框的列表,這會讓人感到困惑。

所以你可以嘗試unlist(... recursive=FALSE),但如果我正確理解你以後的事情,那麼bind_rows()可以做到這一點,只是從你的列表中提取$結果。我猜你的大列表中的每個元素都包含一個名爲results的數據框。

results <- lapply(YOUR_BIG_FAT_LIST, function(x) { 
    df = x$results 
    as.data.frame(address = df$formatted_address, 
     id = df$place_id, 
     lat = df$geometry$location$lat, 
     lng = df$geometry$location$lng)} 
information <- bind_rows(results) 
+0

我得到你的答案,但是我在bind_rows_(x,.id)中得到一個錯誤: 參數1不能是包含數據幀的列表 –

+0

我已經編輯了答案,試圖防止該錯誤。 –

+0

感謝您的努力,但即使發生變化,我也無法獲取數據。可能是我在腳本中做錯了什麼。 –