在不进行转换的情况下将列表中的NULL更改为NA

4
我有一个列表,我正在将其转换为数据框。该列表来自API,其中包含一些NULL值。有关此主题的SO问题在这里这里,但它们要么涉及数据框,要么像第二个链接中那样,鼓励OP首先转换为数据框。我想保留列表结构。
我以下列方式解析它,这是一些示例数据:
example <- list(
  list(
    ID = "1",
    Name = "Joe",
    Middle_name = "Alan",
    Surname = "Smith"
  ),
  list(
    ID = "2",
    Name = "Sarah",
    Middle_name = NULL,
    Surname = "Jones"
  ),
  list(
    ID = "3",
    Name = "Robert",
    Middle_name = "Myles",
    Surname = "McDonnell"
  )
)

N <- NA_character_

df <- tibble::tibble(
  id = purrr::map_chr(example, .null = N, "ID"),
  name = purrr::map_chr(example, .null = N, "Name"),
  middle = purrr::map_chr(example, .null = N, "Middle_name"),
  surname = purrr::map_chr(example, .null = N, "Surname")
)


> df
# A tibble: 3 x 4
     id   name middle   surname
  <chr>  <chr>  <chr>     <chr>
1     1    Joe   <NA>     Smith
2     2  Sarah   <NA>     Jones
3     3 Robert   <NA> McDonnell

看起来这个问题在 purrr 仓库中有一些历史,但是当我使用 purrr 函数比如 is_empty() 或者 compact() 时,要么会出错,要么就不工作。

有人知道怎么做吗?最好能够保持我上面使用的 tibble & map_chr 方法。


为什么你说“我想保留列表结构”,而实际上你想把它转换成数据框架。你确实想把它转换成数据框架,是吗? - Spacedman
1
map_df(transpose(example), ~map_chr(.,~ifelse(is.null(.),NA,.))) 这个怎么样? - HubertL
5
使用 N 个 map_chr 函数进行操作相当于对整个列表进行 N 次迭代。而使用像 lapply 和 rbind 这样逐个元素处理的方式只需对列表进行一次迭代。一个快速的基准测试表明,map_chr 方法比后者慢十倍。这就是为了保持“整洁”而付出的代价。 - Spacedman
1
@Spacedman 谢谢 :-) - RobertMyles
1
@Spacedman 使用 map_chr() N 次等同于使用 vapply() N 次。这并不是 tidyverse 特有的。我们刚刚用 bind_rows()flatten_chr() 进行了基准测试,发现“整洁”的版本实际上比提议的基本版本更快。更重要的是,我们一直在考虑采用列规范方法来解决这类问题。它将把 readr API 带到从列表创建数据框的任务中,并且对于异构列表非常方便。 - Lionel Henry
显示剩余5条评论
1个回答

6
你的示例在purrr的开发版本中可以运行。 NULL行会导致问题,例如使用dplyr::bind_rows将列表嵌套折叠成tibble时。解决方法是循环并flatten每个列表。通过map_df循环绑定行,就可以得到你想要的结果。
map_df(example, flatten)

# A tibble: 3 x 4
     ID   Name Middle_name   Surname
  <chr>  <chr>       <chr>     <chr>
1     1    Joe        Alan     Smith
2     2  Sarah        <NA>     Jones
3     3 Robert       Myles McDonnell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接