2017-05-03 4 views
2

Si vous demandez des données Web via R, vous travaillez souvent avec json ou xml où les champs ne sont pas nommés s'il n'y a pas de valeur pour eux. Parfois, il n'y a même pas de données et il apparaît comme une liste vide pour un certain index. Donc, je vois cela comme deux problèmes différents. Je propose la solution que j'utilise pour résoudre cela, mais je sais qu'il y en a de meilleurs. J'ai pour commencer, une liste très désordonnée et fausse que j'ai créée qui manque des noms de champs (à dessein du xml, json spec) ET des index entiers manquants (également à dessein).Analyse de listes incomplètes dans des blocs de données avec deux problèmes différents

(messy_list <- list(list(x = 2, y = 3), 
        list(), 
        list(y = 4), 
        list(x = 5))) 

Maintenant, voici comment je le décomposer à ce que je dirais est "résolu". Le résultat final est ce que je cherche mais je voudrais trouver une manière plus élégante de faire face à ce problème.

+0

Voulez-vous vraiment conserver les lignes entièrement «NA»? –

+0

Oui. J'ai besoin d'eux dans le même index. – cylondude

Répondre

2

Avec purrr::map_df,

library(purrr) 

messy_list <- list(list(x = 2, y = 3), 
        list(), 
        list(y = 4), 
        list(x = 5)) 

messy_list %>% map_df(~list(x = .x$x %||% NA, 
          y = .x$y %||% NA)) 
#> # A tibble: 4 × 2 
#>  x  y 
#> <dbl> <dbl> 
#> 1  2  3 
#> 2 NA NA 
#> 3 NA  4 
#> 4  5 NA 

map_df itère sur la liste comme lapply et les résultats à contraint un data.frame. La fonction (sous forme de formule de purrr) assemble une liste avec un x et un élément y, recherchant les valeurs existantes si elles sont présentes. Si ce n'est pas le cas, le sous-ensemble renverra NULL, que %||% remplacera par la valeur suivante, NA.

dans la base R essentiellement équivalent,

as.data.frame(do.call(rbind, 
         lapply(messy_list, function(.x){ 
          list(x = ifelse(is.null(.x$x), NA, .x$x), 
           y = ifelse(is.null(.x$y), NA, .x$y)) 
         }))) 
#> x y 
#> 1 2 3 
#> 2 NA NA 
#> 3 NA 4 
#> 4 5 NA 

Notez l'approche de base ne sera pas gérer différents types bien. Pour ce faire, tout contraindre à caractère (rbind sera probablement de toute façon, alors il suffit d'ajouter stringsAsFactors = FALSE à as.data.frame) et lapplytype.convert.

+1

Cela ressemble exactement à ce que je cherchais. Je vais attendre quelques heures et accepter votre réponse si une meilleure ne se présente pas. – cylondude

+0

Pas besoin d'attendre. Marquer avec coche et plus tard vous pouvez toujours le changer. –

2

Votre méthode est déjà assez compact, mais si vous êtes à la recherche d'autres méthodes, d'une façon peut-être utiliser rbindlist de data.table:

library(data.table) 
new_list <- lapply(messy_list, function(x) if(identical(x,list())){list(x = NA)} else {x}) 

rbindlist(new_list, fill = T, use.names = T) 
# x y 
#1: 2 3 
#2: NA NA 
#3: NA 4 
#4: 5 NA 

Remarque nous avons besoin lapply donc il ne tombe pas lignes vides