Фильтровать столбцы фрейма данных на основе значений списка - PullRequest
5 голосов
/ 20 марта 2020

У меня есть фрейм данных как таковой:

df <- data.frame(var1 = c(1,1,3,4,5,6,7,8,9),
       var2 = c(11,11,33,44,55,66,77,88,99),
       var3 = c(111,111,333,444,555,666,777,888,999),
       var4 = c(1111,1111,3333,4444,5555,6666,7777,8888,9999))
> df
  var1 var2 var3 var4
1    1   11  111 1111
2    1   11  111 1111
3    3   33  333 3333
4    4   44  444 4444
5    5   55  555 5555
6    6   66  666 6666
7    7   77  777 7777
8    8   88  888 8888
9    9   99  999 9999

Я хотел бы отфильтровать для определенных c строк на основе нескольких значений столбцов, хранящихся в списке.

Например:

my_list <- list(var1 = 1,
     var2 = 11,
     var3 = 111)
filtered_df <- df %>% filter(var1 == my_list$var1[[1]],
              var2 == my_list$var2[[1]],
              var3 == my_list$var3[[1]])
> filtered_df
  var1 var2 var3 var4
1    1   11  111 1111
2    1   11  111 1111

Вместо того, чтобы включать каждую переменную в filter, могу ли я выбрать элементы в моем списке и отфильтровать фрейм данных, используя имена моего списка?

Ответы [ 4 ]

2 голосов
/ 20 марта 2020

То, что вы предлагаете, очень похоже на естественное в data.table:

library(data.table)
setDT(df)
df[my_list, on = .(var1, var2, var3)]

   var1 var2 var3 var4
1:    1   11  111 1111
2:    1   11  111 1111

Если вы сначала укажете ключи, фильтрация будет более лаконичной:

setkey(df, var1, var2, var3)
df[my_list]

A база R альтернатива:

df[rowSums(df[1:3] == my_list) == 3L, ]
1 голос
/ 20 марта 2020

Вот альтернативный вариант использования rlang::parse_expr():

library(dplyr)
library(rlang)

df %>%
  filter(!!parse_expr(paste(names(my_list), my_list, sep = "==", collapse = "&")))

  var1 var2 var3 var4
1    1   11  111 1111
2    1   11  111 1111
1 голос
/ 20 марта 2020

Одно решение с участием dplyr, tidyr и purrr может быть:

map_dfr(.x = imap(my_list, setNames), 
        ~ enframe(.x) %>%
         inner_join(df %>%
                     rowid_to_column() %>%
                     pivot_longer(-rowid))) %>%
 group_by(rowid) %>%
 filter(n() == length(my_list)) %>%
 slice(1) %>%
 inner_join(df %>%
             rowid_to_column(), by = c("rowid" = "rowid")) %>%
 ungroup() %>%
 select(starts_with("var"))

   var1  var2  var3  var4
  <dbl> <dbl> <dbl> <dbl>
1     1    11   111  1111
2     1    11   111  1111
1 голос
/ 20 марта 2020

Базовое решение R таково:

Сначала вы вставляете значения в ваш список вместе, сворачивая их с помощью маркера чередования |:

my_list_1 <- paste0(unlist(my_list), collapse = "|")
my_list_1
[1] "1|11|111"

Затем, используя эту строку чередования my_list_1, а также вставляя строки вашего фрейма данных вместе с помощью apply, вы подкладываете ваш фрейм данных в те строки, которые соответствуют my_list_1:

df[which(grepl(my_list_1, apply(df, 1, paste0, collapse = " "))),]
  var1 var2 var3 var4
1    1   11  111 1111
2    1   11  111 1111
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...