Различают пустой список или пустой фрейм данных - PullRequest
1 голос
/ 10 мая 2019

Я работаю с API, который, кажется, возвращает искаженные данные.API должен возвращать вложенные фреймы данных, но также иногда возвращает пустые списки:

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

После этого шага я хочу использовать unnest для использования данных во вложенных фреймах данных ниже по потоку.Однако пустые списки мешают этому случиться.Я подумал:

  • (1) Проверить, является ли запись строки пустым списком
  • (2) Если да, преобразовать в пустой фрейм данных;если нет, оставьте как есть.

Однако мои подходы к тестированию пустых списков оказались немного неубедительными, поскольку фрейм данных является списком.В настоящее время я думаю об использовании identical или all.equal в сочетании с dim для теста.А именно, если размеры записи [1,1], то замените эту запись пустым фреймом данных.

(Мне интересно, что происходит в случае, когда у меня есть фрейм данных с измерениями [1,1], но на самом деле в нем тоже есть данные ...)

Это наиболееR способ сделать это?Я видел такое поведение из API в другом месте, поэтому мне нужно будет использовать эту функцию в нескольких местах.

NB Я использую тидиверс, если это влияет на ответы.

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Фрейм данных - это специальный list, но класс dataframe. Вы можете проверить для класса следующим образом:

class(data.frame()) == "list"
> FALSE
class(list()) == "list"
> TRUE
0 голосов
/ 10 мая 2019

Часто проще очистить данные, как только вы получите их из API. Тогда все последующее может опираться на безопасные предположения.

Для этого примера создайте функцию, которая возвращает последовательно отформатированный tbl, используя ответ API. Каждый tbl будет иметь одинаковые столбцы, но некоторые из них могут быть заполнены NA, если их не было в ответе.

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 голосов
/ 10 мая 2019

Вот один вариант с использованием map и if

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

Данные: всегда полезно предоставить воспроизводимые данные о копировании

ir <- iris %>% group_by(Species) %>% nest()
ir$data[[2]]<-list()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...