一般来说,我们如何通过dplyr中的列表变量进行过滤?
E.g。一个数据框,其中一个变量是不同类对象的列表:
aa <- tibble(ss = c(1,2),
dd = list(NA,
matrix(data = c(1,2,3,4),
nrow = 2,
ncol = 2)))
> aa
# A tibble: 2 x 2
# ss dd
# <dbl> <list>
#1 1.00 <lgl [1]>
#2 2.00 <dbl [2 × 2]>
例如,如果我想过滤逻辑(虽然可能是任何东西),如果它不是一个列表,它将简单如下:
aa %>% filter(is.logical(dd))
但是这会返回
# A tibble: 0 x 2
# ... with 2 variables: ss <dbl>, dd <list>
因为它不是第一个符合逻辑的元素,所以它是第一个元素的第一个元素:
> is.logical(aa$dd[1])
# [1] FALSE
> is.logical(aa$dd[[1]])
# [1] TRUE
可以使用purrr:map
对嵌套列表变量进行其他操作,但这也不起作用。
> aa %>% filter(map(.x = dd,
+ .f = is.logical))
# Error in filter_impl(.data, quo) : basic_string::resize
我在这里缺少什么?
答案 0 :(得分:4)
作为&#39; dd&#39;是一个list
列,我们可以遍历&#39; dd&#39;使用map
,但每个元素都是&#39; dd&#39;可以有多个元素,因此我们要求all
元素为NA
,然后filter
数据集的行
library(tidyverse)
aa %>%
filter(map_lgl(dd, ~ .x %>%
is.na %>%
all))
# A tibble: 1 x 2
# ss dd
# <dbl> <list>
#1 1 <lgl [1]>
如果这是filter
基于class
。
aa %>%
filter(map_lgl(dd, is.logical))
# A tibble: 1 x 2
# ss dd
# <dbl> <list>
#1 1 <lgl [1]>
在OP的代码中,map
输出仍为list
,我们将其转换为map_lgl
答案 1 :(得分:1)
我能做的最好的事情是使用is.logical
创建一个虚拟变量,purrr:map
,unlist
,filter
,然后取消 - select
虚拟变量。工作,但是什么是kerfuffle。
aa %>%
mutate(ff = map(.x = dd,
.f = is.logical),
ff = unlist(ff)) %>%
filter(ff == TRUE) %>%
select(-ff)
# A tibble: 1 x 2
# ss dd
# <dbl> <list>
# 1 1.00 <lgl [1]>