2017-09-05 2 views
0

J'ai une liste imbriquée d'adresses de rue géocodées de Moscou, converties à partir d'une liste imbriquée. Cependant, la base de données que je géocodais n'avait que des adresses sans codes postaux, et dans quelques centaines (sur 33k) cas, l'adresse renvoyait plusieurs résultats pour la même adresse avec différents codes postaux. Cela a créé une imbrication supplémentaire dans la liste, qui, une fois convertie en une base de données, entraîne un nombre différent d'observations à partir de la trame de données initiale.La liste d'aplatissement avec des niveaux d'imbrication variables crée des observations supplémentaires

Un résultat avec une seule adresse a la structure suivante: (Ignorer le charabia, console R ne rend pas cyrillique correctement)

structure(list(results = structure(list(address_components = list(
    structure(list(long_name = c("4", "óëèöà Áîëüøàÿ Àêàäåìè÷åñêàÿ", 
    "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", "Ìîñêâà", "Ìîñêâà", "Ðîññèÿ", 
    "127299"), short_name = c("4", "óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ", 
    "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", "Ìîñêâà", "Ìîñêâà", "RU", 
    "127299"), types = list("street_number", "route", c("political", 
    "sublocality", "sublocality_level_1"), c("locality", "political" 
    ), c("administrative_area_level_2", "political"), c("country", 
    "political"), "postal_code")), .Names = c("long_name", "short_name", 
    "types"), class = "data.frame", row.names = c(NA, 7L))), 
    formatted_address = "óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ, 4, Ìîñêâà, Ðîññèÿ, 127299", 
    geometry = structure(list(location = structure(list(lat = 55.8176896, 
     lng = 37.522891), .Names = c("lat", "lng"), class = "data.frame", row.names = 1L), 
     location_type = "ROOFTOP", viewport = structure(list(
      northeast = structure(list(lat = 55.8190385802915, 
       lng = 37.5242399802915), .Names = c("lat", "lng" 
      ), class = "data.frame", row.names = 1L), southwest = structure(list(
       lat = 55.8163406197085, lng = 37.5215420197085), .Names = c("lat", 
      "lng"), class = "data.frame", row.names = 1L)), .Names = c("northeast", 
     "southwest"), class = "data.frame", row.names = 1L)), .Names = c("location", 
    "location_type", "viewport"), class = "data.frame", row.names = 1L), 
    partial_match = TRUE, place_id = "ChIJ59yLsy1ItUYR5EEBFbFJoSA", 
    types = list("street_address")), .Names = c("address_components", 
"formatted_address", "geometry", "partial_match", "place_id", 
"types"), class = "data.frame", row.names = 1L), status = "OK"), .Names = c("results", 
"status")) 

Alors qu'un résultat avec plusieurs adresses possibles ressemble:

structure(list(results = structure(list(address_components = list(
    structure(list(long_name = c("23", "óëèöà Áîëüøàÿ Àêàäåìè÷åñêàÿ", 
    "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", "Ìîñêâà", "Ìîñêâà", "Ðîññèÿ", 
    "127299"), short_name = c("23", "óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ", 
    "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", "Ìîñêâà", "Ìîñêâà", "RU", 
    "127299"), types = list("street_number", "route", c("political", 
    "sublocality", "sublocality_level_1"), c("locality", "political" 
    ), c("administrative_area_level_2", "political"), c("country", 
    "political"), "postal_code")), .Names = c("long_name", "short_name", 
    "types"), class = "data.frame", row.names = c(NA, 7L)), structure(list(
     long_name = c("23", "óëèöà Áîëüøàÿ Àêàäåìè÷åñêàÿ", "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", 
     "Ìîñêâà", "Ìîñêâà", "Ðîññèÿ", "125008"), short_name = c("23", 
     "óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ", "Ñåâåðíûé àäìèíèñòðàòèâíûé îêðóã", 
     "Ìîñêâà", "Ìîñêâà", "RU", "125008"), types = list("street_number", 
      "route", c("political", "sublocality", "sublocality_level_1" 
      ), c("locality", "political"), c("administrative_area_level_2", 
      "political"), c("country", "political"), "postal_code")), .Names = c("long_name", 
    "short_name", "types"), class = "data.frame", row.names = c(NA, 
    7L))), formatted_address = c("óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ, 23, Ìîñêâà, Ðîññèÿ, 127299", 
"óë. Áîëüøàÿ Àêàäåìè÷åñêàÿ, 23, Ìîñêâà, Ðîññèÿ, 125008"), geometry = structure(list(
    location = structure(list(lat = c(55.8169112, 55.826859), 
     lng = c(37.5202899, 37.529427)), .Names = c("lat", "lng" 
    ), class = "data.frame", row.names = 1:2), location_type = c("ROOFTOP", 
    "ROOFTOP"), viewport = structure(list(northeast = structure(list(
     lat = c(55.8182601802915, 55.8282079802915), lng = c(37.5216388802915, 
     37.5307759802915)), .Names = c("lat", "lng"), class = "data.frame", row.names = 1:2), 
     southwest = structure(list(lat = c(55.8155622197085, 
     55.8255100197085), lng = c(37.5189409197085, 37.5280780197085 
     )), .Names = c("lat", "lng"), class = "data.frame", row.names = 1:2)), .Names = c("northeast", 
    "southwest"), class = "data.frame", row.names = 1:2)), .Names = c("location", 
"location_type", "viewport"), class = "data.frame", row.names = 1:2), 
    partial_match = c(TRUE, TRUE), place_id = c("ChIJnVMw7C1ItUYRdfeWEQrXuAk", 
    "ChIJnbnwOdY3tUYR1_D9pHTqCsI"), types = list("street_address", 
     "street_address")), .Names = c("address_components", 
"formatted_address", "geometry", "partial_match", "place_id", 
"types"), class = "data.frame", row.names = 1:2), status = "OK"), .Names = c("results", 
"status")) 

Dans l'élément de résultat de la deuxième liste, il existe un niveau d'imbrication supplémentaire pour chaque adresse possible, ce qui, lorsqu'il est aplati, crée une observation «supplémentaire» pour cette adresse, ce qui rend impossible l'accès à cbind() renvoie le géocodage à la liste des adresses. J'utilise les fonctions suivantes pour aplatir mes listes imbriquées en trames de données. Comment puis-je les modifier pour ne prendre que la première adresse lorsque cette imbrication supplémentaire se produit? Si l'adresse est incorrecte, les bâtiments seront simplement supprimés de l'échantillon quand je fusionnerai plus tard avec une autre base de données, donc je me contente de faire correspondre chaque observation géocodée à la rangée appropriée dans la base de données originale (la source des adresses).

flatten_googleway <- function(df) { 
    require(jsonlite) 
    res <- jsonlite::flatten(df) 
    res[, names(res) %in% c("geometry.location_type", "geometry.location.lat", 
          "geometry.location.lng", "formatted_address")] 
} 
moscowhousegeo.df <- do.call(rbind, lapply(moscowhouse.list, function(x) { 
    if (length(x$results) == 0) template_res[1, ] else flatten_googleway(x$results) 
})) 

##template for NA results 
structure(list(formatted_address = character(0), geometry.location_type = character(0), 
    geometry.location.lat = numeric(0), geometry.location.lng = numeric(0)), .Names = c("formatted_address", 
"geometry.location_type", "geometry.location.lat", "geometry.location.lng" 
), row.names = integer(0), class = "data.frame") 

Répondre

0

Oups, je compliquais massivement les choses, comme d'habitude. J'ai été capable de résoudre ce problème simplement en modifiant l'appel lapply() pour remplacer tous les éléments de la liste sans résultat, et les éléments où x$results$address_components est supérieur à la longueur 1 (comme c'est le cas lorsque plusieurs résultats possibles sont renvoyés).

moscowhousegeo.df <- do.call(rbind, lapply(moscowhouse.list, function(x) { 
    if (length(x$results) == 0 | length(x$results$formatted_address) > 1) template_res[1, ] else flatten_googleway(x$results) 
})) 

je perds encore des données de cette façon, malheureusement, mais identifier quelle adresse est correcte sur les options disponibles seraient probablement trop de temps, et un peu bête dans un jeu de données avec tant d'observations.