在dplyr中过滤列表变量

时间:2018-05-29 04:52:06

标签: r dplyr

一般来说,我们如何通过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

我在这里缺少什么?

2 个答案:

答案 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:mapunlistfilter,然后取消 - 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]>