Поиск строк большой матрицы, соответствующих определенным значениям

Моя цель - найти индексы строк матрицы (dat), которые содержат совпадающие строки другой матрицы (xy).

Я считаю, что это легко сделать с меньшими матрицами, как показано в примерах. Но в матрицах у меня очень большое количество строк.

Для примера ниже приведены матрицы dat и xy. Задача - восстановить индексы 14, 58, 99. В моем случае обе эти матрицы имеют очень большее количество строк.

# toy data
dat <- iris
dat$Sepal.Length <- dat$Sepal.Length * (1 + runif (150))

xy <- dat[c(14, 58, 99), c(1, 5)]

Для небольших матриц решения были бы

# solution 1
ind <- NULL
for(j in 1 : length(x)) {

  ind[j] <- which((dat$Sepal.Length ==xy[j, 1]) & (dat$Species == xy[j, 2]))
}

Или

# solution 2
which(outer(dat$Sepal.Length, xy[, 1], "= = ") & 
        outer(dat$Species, xy[, 2], "= = "), arr.ind=TRUE)

Но, учитывая размер моих данных, эти методы неосуществимы. Первый метод занимает много времени, а второй не работает из-за нехватки памяти.

Хотел бы я узнать больше о data.table и dplyr.

Похоже на обман. Вы можете использовать соединение, чтобы найти точные совпадения. Что-то вроде xy [dat, on =. (Длина, виды)]

chinsoon12 15.09.2018 00:47

Это могло быть обманом. Я действительно хорошо посмотрел, но все же, возможно, я это пропустил.

Suren 15.09.2018 01:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
236
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Вы можете попробовать это решение dplyr. Зависит от размера ваших фреймов данных.

#use dplyr filter
library(dplyr)

dat %>%
  mutate(row_no = row_number()) %>%
  filter(Sepal.Length %in% xy$Sepal.Length & Species %in% xy$Species) %>%
  select(row_no)
#>   row_no
#> 1     14
#> 2     58
#> 3     99

Спасибо. Я попробую и вернусь. В dat примерно полмиллиона строк.

Suren 15.09.2018 01:08

Я использовал paste0 () для объединения Sepal.Length и Species во временную переменную.

Затем соответствие(), чтобы вернуть индекс совпадений между двумя временными переменными.

Тогда нет, '!', is.na (), чтобы удалить несовпадения и преобразовать в логический вектор.

Затем верните который(), индексы верны.

which(!is.na(match(paste0(dat$Sepal.Length, dat$Species), paste0(xy$Sepal.Length, xy$Species))))

[1] 14 58 99

PS: merge () принимает комбинированные переменные в by.x и by.y:

merge(dat, xy, by.x=c("Sepal.Length", "Species"), by.y=c("Sepal.Length", "Species"), all.x=FALSE, all.y=TRUE)

Следуя предложению chinsoon12, попробуйте следующее:

library(dplyr)
dat$rowind <- 1:nrow(dat) # adds row index if wanted (not necessary though)
newDf <- semi_join(dat, xy, by = c("Species", "Sepal.Length"))

Для предоставленной вами настройки вы можете использовать:

library(tidyverse)
dat %>% 
  mutate(row_num = row_number()) %>% 
  inner_join(xy, by = c("Sepal.Length", "Species")) %>%
  pull(row_num)

Это добавляет столбец для начального номера строки, выполняет внутреннее соединение для создания фрейма данных со строками в dat, которые соответствуют строкам из xy, а затем извлекает индексы. (Внутреннее соединение вернет все строки из dat, которые соответствуют строкам из xy, а полусоединение вернет только одну строку из dat для каждой строки в xy.)

Стоит отметить, что в этом примере мы имеем дело с фреймами данных, а не с матрицами:

> class(xy)
[1] "data.frame"
> class(dat)
[1] "data.frame"

Приведенный выше код не будет работать, если данные находятся в матричной форме - можете ли вы преобразовать свои матрицы во фреймы данных или таблицы?

Спасибо. Да, их можно преобразовать в data.frame или tibble.

Suren 15.09.2018 01:23

если ваши данные огромны, вы можете сначала хэшировать свои строки (для обеих матриц), а затем сопоставить значения хэша строк, используя пакет дайджеста.

target_matrix<-iris
query_matrix<-iris[c(14, 58, 99),]
target_row_hash<-apply(target_matrix,1,digest)
query_row_hash<-apply(query_matrix,1,digest)
row_nums<-match(query_row_hash,target_row_hash)
row_nums

выход:

14 58 99

С data.table это соединение:

library(data.table)
setDT(dat); setDT(xy)

dat[xy, on=names(xy), which=TRUE]
# [1] 14 58 99

Другие вопросы по теме