R - 是否可以取消嵌套包含缺失 (NA) 值的 list-column?
R - Is it possible to unnest a list-column that contains missing (NA) values?
下面的小标题有一个 list-column property
,其中包含一些缺失值:
library(tidyverse)
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2))
# A tibble: 4 x 2
type property
<chr> <list>
1 scale <list [2]>
2 range <lgl [1]>
3 min <list [2]>
4 max <lgl [1]>
我想取消嵌套此列,然后将结果展开为具有三列的宽格式 - type
、lttr
和 mth
:
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2)) %>%
mutate(property = map_if(property, is_list, enframe)) %>%
unnest(property) %>%
spread(name, value)
但是,unnest
调用会引发以下错误:
Error: Each column must either be a list of vectors or a list of data frames [property]
我在 Git 上遇到了一个类似的问题,要求 unnest
支持 NULL
值但没有提及 NAs
。函数文档中似乎也没有任何与缺失有关的参数,但我可能是错的。
如果过滤掉 NAs
,管道将按预期工作:
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2)) %>%
mutate(property = map_if(property, is_list, enframe)) %>%
filter(!is.na(property)) %>% # drop_na() and na_omit not working not sure why
unnest(property) %>%
spread(name, value)
tbl
# A tibble: 2 x 3
type lttr mth
<chr> <list> <list>
1 min <chr [26]> <chr [12]>
2 scale <chr [26]> <chr [12]>
如何 unnest
ing tbl
、group_by
type
然后使用 summarise
创建新列?
library(dplyr)
library(tidyr)
tbl %>%
unnest() %>%
group_by(type) %>%
summarise(lttr = property[1L],
mth = property[2L])
# type lttr mth
# <chr> <list> <list>
#1 max <NULL> <NULL>
#2 min <chr [26]> <chr [12]>
#3 range <NULL> <NULL>
#4 scale <chr [26]> <chr [12]>
一个选项是将所有内容都转换为 tibble
,这样 unnest
结构在整个过程中都是相同的,而不是手动设置子集
library(tidyverse)
tbl %>%
mutate(property = map(property, ~ if(!is.list(.x))
enframe(list(nm1 = .x)) else enframe(.x))) %>%
unnest %>%
spread(name, value) %>%
select(type, lttr, mth)
# A tibble: 4 x 3
# type lttr mth
# <chr> <list> <list>
#1 max <NULL> <NULL>
#2 min <chr [26]> <chr [12]>
#3 range <NULL> <NULL>
#4 scale <chr [26]> <chr [12]>
OP 示例中的问题是 NA
行与其他行相比的结构差异。当我们 filter
他们出来时,结构是相同的,问题得到解决
我们还可以检查另一个示例,其中 list
个元素的数量大于 2。
tbl1 <- tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name,
val1 = rnorm(12), val2 = runif(12)), NA) %>%
rep(., 2))
tbl1 %>%
mutate(property = map(property, ~ if(!is.list(.x)) enframe(list(nm1 = .x))
else enframe(.x))) %>%
unnest %>%
spread(name, value) %>%
select(-nm1)
# A tibble: 4 x 5
# type lttr mth val1 val2
# <chr> <list> <list> <list> <list>
#1 max <NULL> <NULL> <NULL> <NULL>
#2 min <chr [26]> <chr [12]> <dbl [12]> <dbl [12]>
#3 range <NULL> <NULL> <NULL> <NULL>
#4 scale <chr [26]> <chr [12]> <dbl [12]> <dbl [12]>
这可以扩展到任意数量的元素
下面的小标题有一个 list-column property
,其中包含一些缺失值:
library(tidyverse)
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2))
# A tibble: 4 x 2
type property
<chr> <list>
1 scale <list [2]>
2 range <lgl [1]>
3 min <list [2]>
4 max <lgl [1]>
我想取消嵌套此列,然后将结果展开为具有三列的宽格式 - type
、lttr
和 mth
:
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2)) %>%
mutate(property = map_if(property, is_list, enframe)) %>%
unnest(property) %>%
spread(name, value)
但是,unnest
调用会引发以下错误:
Error: Each column must either be a list of vectors or a list of data frames [property]
我在 Git 上遇到了一个类似的问题,要求 unnest
支持 NULL
值但没有提及 NAs
。函数文档中似乎也没有任何与缺失有关的参数,但我可能是错的。
如果过滤掉 NAs
,管道将按预期工作:
tbl = tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name), NA) %>%
rep(., 2)) %>%
mutate(property = map_if(property, is_list, enframe)) %>%
filter(!is.na(property)) %>% # drop_na() and na_omit not working not sure why
unnest(property) %>%
spread(name, value)
tbl
# A tibble: 2 x 3
type lttr mth
<chr> <list> <list>
1 min <chr [26]> <chr [12]>
2 scale <chr [26]> <chr [12]>
如何 unnest
ing tbl
、group_by
type
然后使用 summarise
创建新列?
library(dplyr)
library(tidyr)
tbl %>%
unnest() %>%
group_by(type) %>%
summarise(lttr = property[1L],
mth = property[2L])
# type lttr mth
# <chr> <list> <list>
#1 max <NULL> <NULL>
#2 min <chr [26]> <chr [12]>
#3 range <NULL> <NULL>
#4 scale <chr [26]> <chr [12]>
一个选项是将所有内容都转换为 tibble
,这样 unnest
结构在整个过程中都是相同的,而不是手动设置子集
library(tidyverse)
tbl %>%
mutate(property = map(property, ~ if(!is.list(.x))
enframe(list(nm1 = .x)) else enframe(.x))) %>%
unnest %>%
spread(name, value) %>%
select(type, lttr, mth)
# A tibble: 4 x 3
# type lttr mth
# <chr> <list> <list>
#1 max <NULL> <NULL>
#2 min <chr [26]> <chr [12]>
#3 range <NULL> <NULL>
#4 scale <chr [26]> <chr [12]>
OP 示例中的问题是 NA
行与其他行相比的结构差异。当我们 filter
他们出来时,结构是相同的,问题得到解决
我们还可以检查另一个示例,其中 list
个元素的数量大于 2。
tbl1 <- tibble(type = c('scale', 'range', 'min', 'max'),
property = list(list(lttr = letters, mth = month.name,
val1 = rnorm(12), val2 = runif(12)), NA) %>%
rep(., 2))
tbl1 %>%
mutate(property = map(property, ~ if(!is.list(.x)) enframe(list(nm1 = .x))
else enframe(.x))) %>%
unnest %>%
spread(name, value) %>%
select(-nm1)
# A tibble: 4 x 5
# type lttr mth val1 val2
# <chr> <list> <list> <list> <list>
#1 max <NULL> <NULL> <NULL> <NULL>
#2 min <chr [26]> <chr [12]> <dbl [12]> <dbl [12]>
#3 range <NULL> <NULL> <NULL> <NULL>
#4 scale <chr [26]> <chr [12]> <dbl [12]> <dbl [12]>
这可以扩展到任意数量的元素