Найти несколько строк во всем фрейме данных - PullRequest
2 голосов
/ 13 июня 2019

Я пытаюсь найти несколько строк в моем фрейме данных, используя функцию which.Я пытаюсь продлить ответ от Найти строку в data.frame

Пример кадра данных:

df1 <- data.frame(animal=c('a','b','c','two', 'five', 'c'), level=c('five','one','three',30,'horse', 'five'), length=c(10, 20, 30, 'horse', 'eight', 'c'))

1      a  five     10
2      b   one     20
3      c three     30
4    two    30  horse
5   five horse  eight
6      c  five      c 

onэтот кадр данных, когда я применяю функцию which для одной строки, я получаю правильный вывод, например, which(df1 =="c" , arr.ind = T);df1 дает:

  row col
[1,]   3   1
[2,]   6   1
[3,]   6   3

Но когда я пытаюсь найти несколько строк, я получаю только частично правильный вывод, напримерwhich(df1 ==c("c", "horse", "five") , arr.ind = T)

  row col
[1,]   5   2
[2,]   6   2

Ожидаемый результат должен быть:

     row col
[1,]   3   1
[2,]   5   1
[3,]   6   1
[4,]   1   2
[5,]   5   2
[6,]   6   2
[7,]   4   3
[8,]   6   3

Отсюда мой вопрос:

  1. почему решение с c ("с", "лошадь", "пять") не работает?

  2. Я пробовал с

which(df1=="c" | df1=="horse" | df1 =="five", arr.ind = T)

, который дает мне правильный вывод, но для многих строк слишком длинный, как я могу сделать мой код лаконичным?

Ответы [ 2 ]

2 голосов
/ 13 июня 2019

Поскольку у вас есть несколько значений, вы не можете напрямую сравнивать их в кадре данных.Одним из способов является использование sapply с grepl путем создания границ слов и проверки наличия шаблона в каком-либо из столбцов, а затем использование which для получения индексов строк и столбцов.

vals <- c("c", "horse", "five") 

which(sapply(df1, grepl, pattern = paste0("\\b", vals, "\\b", collapse = "|")), 
      arr.ind = TRUE)

#     row col
#[1,]   3   1
#[2,]   5   1
#[3,]   6   1
#[4,]   1   2
#[5,]   5   2
#[6,]   6   2
#[7,]   4   3
#[8,]   6   3
2 голосов
/ 13 июня 2019

Мы можем перебрать вектор с помощью lapply, сделать ==, Reduce его единичной логической матрицей с | и обернуть с помощью which

which(Reduce(`|`, lapply(c("c", "horse", "five"), `==`, df1)), arr.ind = TRUE)
#     row col
#[1,]   3   1
#[2,]   5   1
#[3,]   6   1
#[4,]   1   2
#[5,]   5   2
#[6,]   6   2
#[7,]   4   3
#[8,]   6   3

Или другой вариант - циклически перебирать столбцы набора данных с помощью mutate_all и переносить с помощью which

library(dplyr)
df1 %>%
  mutate_all(list(~ . %in% c("c", "horse", "five"))) %>%
  as.matrix %>% 
  which(., arr.ind = TRUE)

ПРИМЕЧАНИЕ. Здесь нам не нужно никаких регулярных выражений или частичных совпадений, если OP хотел выполнить полное совпадение строк. Это должно быть быстрее, чем делать какие-либо частичные совпадения


Обычно для нескольких элементов было бы полезно %in%, но оно работает только для вектора, а не для data.frame

...