1
votes

Distinguer une liste vide ou un bloc de données vide

Je travaille avec une API qui semble renvoyer des données mal formées. L'API doit renvoyer des cadres de données imbriqués, mais renvoie également des listes vides à l'occasion:

column_name
<list>
<data.frame [1 × 5]>                
<data.frame [0 × 0]>                
<data.frame [0 × 0]>                
<list [0]>
...

Après cette étape, je souhaite utiliser unnest pour utiliser les données dans les trames de données en aval. Cependant, les listes vides empêchent cela de se produire. Ce que j'ai pensé à faire est:

  • (1) Test pour voir si l'entrée de ligne est une liste vide
  • (2) Si oui, convertir en un bloc de données vide; si non, laissez tel quel

Cependant, mes approches de test pour les listes vides sont tombées un peu à plat, car un bloc de données est une liste. Actuellement, je pense à utiliser identique ou all.equal en conjonction avec dim pour le test. À savoir si les dimensions de l'entrée sont [1,1], remplacez cette entrée par un bloc de données vide.

(Je me demande ce qui se passe dans le cas où j'ai un bloc de données avec des dimensions [1,1] mais contient en fait des données aussi ...)

Est-ce le plus la façon la plus R de faire cela? J'ai vu ce comportement de l'API ailleurs, je vais donc devoir utiliser cette fonctionnalité à plusieurs endroits.

NB J'utilise le tidyverse, si cela a un impact sur les réponses.


2 commentaires

Qu'en est-il de la class (data.frame ()) == "list" et de la class (list ()) == "list"


ou is.data.frame (list ()) pour votre test.


3 Réponses :


1
votes

Un dataframe est une liste spéciale mais la classe est dataframe . Vous pouvez tester la classe de cette façon:

class(data.frame()) == "list"
> FALSE
class(list()) == "list"
> TRUE


0 commentaires

1
votes

Voici une option utilisant map et if

ir <- iris %>% group_by(Species) %>% nest()
ir$data[[2]]<-list()

Données: fournir des données reproductibles par copier-coller est toujours utile p >

library(dplyr)
library(purrr)  
ir %>% mutate(data1=map(data, ~if(is.null(dim(.x))) data.frame() else .x)) %>% 
       unnest(data1)


0 commentaires

0
votes

Il est souvent plus facile de nettoyer les données dès que vous les récupérez depuis l'API. Ensuite, tout ce qui suit peut reposer sur des hypothèses sûres.

Pour cet exemple, créez une fonction qui renvoie un tbl au format cohérent en utilisant la réponse de l'API. Chaque tbl aura les mêmes colonnes, mais certaines d'entre elles pourraient être remplies avec NA si elles ne figuraient pas dans la réponse.

library(tidyr)
library(dplyr)

response_to_df <- function(id = NA_real_,
                           country = NA_character_,
                           wealth = NA_real_,
                           ... # Catch extra columns you don't want
                           ) {
  tibble(id = id, country = country, wealth = wealth)
}

prepare_response_df <- function(response) {
  do.call(response_to_df, response)
}

responses <- list(
  tibble(id = 1:2, country = c("US", "DE"), wealth = c(95, 84)),
  list(),
  tibble(id = 3)
)

tibble(res = responses) %>%
  mutate(nicer = lapply(res, prepare_response_df)) %>%
  unnest(nicer)
# # A tibble: 4 x 3
#      id country wealth
#   <dbl> <chr>    <dbl>
# 1     1 US          95
# 2     2 DE          84
# 3    NA NA          NA
# 4     3 NA          NA


0 commentaires