R: Создать новый список значений на основе столбцов из нескольких столбцов - PullRequest
1 голос
/ 09 февраля 2020

Я хочу создать новый столбец (T / F) на основе любого значения из списка, присутствующего в нескольких столбцах. Для этого примера я использую mtcars для своего примера, ища два значения в двух столбцах, но моя настоящая проблема - много значений во многих столбцах.

У меня есть успешный фильтр, использующий filter_at(), включенный ниже, но я не смог применить эту логику c к мутации:

# there are 7 cars with 6 cyl
mtcars %>%
  filter(cyl == 6)

# there are 2 cars with 19.2 mpg, one with 6 cyl, one with 8
mtcars %>% 
  filter(mpg == 19.2)

# there are 8 rows with either.
# these are the rows I want as TRUE
mtcars %>% 
  filter(mpg == 19.2 | cyl == 6)

# set the cols to look at
mtcars_cols <- mtcars %>% 
  select(matches('^(mp|cy)')) %>% names()

# set the values to look at
mtcars_numbs <- c(19.2, 6)

# result is 8 vars with either value in either col.
# this is a successful filter of the data
out1 <- mtcars %>% 
    filter_at(vars(mtcars_cols), any_vars(
        . %in% mtcars_numbs
        )
      )

# shows set with all 6 cyl, plus one 8cyl 21.9 mpg
out1 %>% 
  select(mpg, cyl)

# This attempts to apply the filter list to the cols,
# but I only get 6 rows as True
# I tried to change == to %in& but that results in an error
out2 <- mtcars %>%
    mutate(
      myset = rowSums(select(., mtcars_cols) == mtcars_numbs) > 0
    )

# only 6 rows returned
out2 %>% 
  filter(myset == T)

Я не уверен, почему пропущены две строки. Я думаю это может быть использование rowSums, которое каким-то образом агрегирует эти две строки.

1 Ответ

1 голос
/ 09 февраля 2020

Если мы хотим выполнить соответствующие проверки, может быть лучше использовать map2

 library(dplyr)
 library(purrr)
 map2_df(mtcars_cols, mtcars_numbs, ~ 
       mtcars %>%
           filter(!! rlang::sym(.x) == .y)) %>%
     distinct

ПРИМЕЧАНИЕ. Сравнение (==) с числами с плавающей запятой может привести к проблемам, так как точность может варьироваться и приводить к FALSE


Кроме того, обратите внимание, что == работает только тогда, когда элементы lhs и rhs имеют одинаковую длину или вектор rhs имеет length 1 (здесь происходит переработка). Если length больше 1 и не равно длине вектора lhs, рециркуляция будет сравниваться в порядке столбцов.

Мы можем rep разрешить сделать длину равной, и теперь она должна работать

mtcars %>%
 mutate(
   myset = rowSums(select(., mtcars_cols) == mtcars_numbs[col(select(., mtcars_cols))]) > 0
   ) %>% pull(myset) %>% sum
#[1] 8

В приведенном выше коде select используется дважды для лучшего понимания. В противном случае мы также можем использовать rep

mtcars %>%
 mutate(
   myset = rowSums(select(., mtcars_cols) == rep(mtcars_numbs, each = n())) > 0
    ) %>% 
   pull(myset) %>%
   sum
#[1] 8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...