Выбирать строки только в том случае, если они соответствуют определенной строке

У меня есть набор данных с 5 числовыми столбцами, например {A,B,C,D,E}, в котором значение любого столбца может варьироваться от 1 до 100, т. е.

1 <= все значения в A/B/C/D/E <= 100

и наш набор данных выглядит так:

A  B  C  D  E  
1  5  7  19 2    
90 12 8  45 30  
30 10 20 50 40 #need this row  
33 11 22 55 44  
50 40 10 20 30 #and this row  
40 40 10 20 30 #not this one

и я хочу отфильтровать только те строки, которые содержат каждое из следующих 5 значений, например: {10,20,30,40,50}. порядок не имеет значения, но 5 столбцов должны содержать все 5 значений.

Таким образом, вывод должен быть таким:

A  B  C  D  E    
30 10 20 50 40  
50 40 10 20 30

Я пытался использовать много ifelse для фильтрации всех условий из 5 столбцов, но дело в том, что мне нужно применить эту концепцию к более сложной проблеме, где они могут не быть определенными нет. столбцов или даже определенный набор данных «поиск». поэтому любое решение с использованием dplyr, data.table, tidyverse высоко ценится, но любое другое творческое решение, которое кто-либо может придумать, пожалуйста, поделитесь.

Стоит ли изучать 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
0
321
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Может быть, что-то вроде этого?

library(dplyr)

dat %>%
  rowwise() %>%
  filter(paste(sort(c(A, B, C, D, E)), collapse = ".") == "10.20.30.40.50") %>%
  ungroup()

# A tibble: 2 x 5
      A     B     C     D     E
  <int> <int> <int> <int> <int>
1    30    10    20    50    40
2    50    40    10    20    30

Данные:

dat <- read.table(text = "A  B  C  D  E  
1  5  7  19 2    
90 12 8  45 30  
30 10 20 50 40
33 11 22 55 44  
50 40 10 20 30
40 40 10 20 30", header = TRUE)

Примечание. Я не уверен, что это будет хорошим подходом для расширения вашего «более сложная проблема, когда они могут не быть определенным количеством столбцов или даже определенным набором данных для поиска», так как это несколько расплывчато определено. Если у вас есть более сложная проблема, я настоятельно рекомендую вам сформулировать свой вопрос так, чтобы отразить ее.

Вот метод преобразования в длинный формат, фильтрация и изменение формы обратно в широкий:

my_vals = c(10, 20, 30, 40, 50)

library(tidyr)
library(dplyr)
df %>% mutate(id = row_number()) %>%
  gather("col", "val", -id) %>%
  group_by(id) %>%
  filter(all(my_vals %in% val)) %>%
  spread(col, val)

# A tibble: 2 x 6
# Groups:   id [2]
     id     A     B     C     D     E
  <int> <int> <int> <int> <int> <int>
1     3    30    10    20    50    40
2     5    50    40    10    20    30

(Конечно, вы можете убрать столбец id, если он вам не нужен.)

Ответ принят как подходящий
tb <- data.frame(A = c(1, 90, 30 ,33,50,40),
                 B = c(5,12,10,11,40,40),
                 C = c(7,8,20,22,10,10),
                 D = c(19,45,50,55,20,20),
                 E = c(2,30,40,44,30,30))

cols <- paste0(c(10,20,30,40,50), collapse = "_")

index <- apply(tb, 1, function(x) paste0(sort(x), collapse = "_") == cols)

tb[index,]

Спасибо! изменение строк в строки, а затем их сравнение, что на самом деле помогает мне больше.

Sudhanshu Bansal 24.04.2019 18:44

Вот решение data.table:

library(data.table)

dt <- setDT(read.table(text = "A  B  C  D  E  
  1  5  7  19 2    
  90 12 8  45 30  
  30 10 20 50 40
  33 11 22 55 44  
  50 40 10 20 30
  40 40 10 20 30", header = TRUE))

dt = dt[, .SD[all(seq(10, 50, 10) %in% .SD)], by = 1:nrow(dt)]

Используя apply, sum и %in% из базы R

my_vals = c(10, 20, 30, 40, 50)
df[apply(df, 1, function(row) all(my_vals %in% row)), ]

   A  B  C  D  E
3 30 10 20 50 40
5 50 40 10 20 30

Это может быть расширено на любое количество столбцов, и все, что вам нужно сделать, это обновить my_vals.

Редактировать

Основываясь на комментарии OP относительно ситуации, когда нужно выбрать правильные строки, когда my_vals может иметь повторяющиеся элементы, приведенный выше код можно изменить примерно так:

my_vals = sort(c(10, 20, 30, 40, 40))
df[apply(df, 1, function(row) all(my_vals == sort(row))), ]

   A  B  C  D  E
6 40 40 10 20 30

к вашему сведению, когда my_vals = c(10, 20, 30, 40, 40), это решение тоже подхватит c(10, 20, 30, 40, 50)

chinsoon12 24.04.2019 03:24

Ах, да, потому что это не было перечисленным вариантом использования. Итак, в таком случае вам не нужна строка с 50? Потому что, учитывая ваше условие в вопросе, если в строке есть 10,20,30,40,50, в ней все еще есть все элементы, указанные в my_vals = c(10, 20, 30, 40, 40), плюс дополнительные 50.

cropgen 24.04.2019 03:46

ты прав. с my_vals = c(10, 20, 30, 40, 40) он также выберет 5-ю строку в моем наборе данных. и я не хочу этого, так как важно, чтобы выбирались только строки, которые также имеют столько же экземпляров всех значений в my_vals. Я имею в виду, что если my_vals = c(10, 20, 30, 40, 40), то будет выбрана только строка с двумя 40, одной 30, одной 20 и одной 10... надеюсь, это достаточно ясно.

Sudhanshu Bansal 24.04.2019 18:40

Я обновил ответ, чтобы учесть ваше новое условие

cropgen 24.04.2019 20:42

@nsinghs Спасибо за редактирование. Это работает лучше для меня сейчас.

Sudhanshu Bansal 27.04.2019 12:46

Вот еще вариант без сортировки каждой строки.

Идея состоит в том, чтобы соединить каждый столбец набора данных со значениями поиска, столбец за столбцом. Например, для столбца A используйте все 5 значений для фильтрации исходного набора данных.

Затем для столбца B выполните соединение, используя то, что не использовалось в столбце A для каждого подмножества набора данных из предыдущего шага.

Затем для столбца C выполните соединение, используя то, что не использовалось в столбцах A и B для каждого подмножества набора данных из предыдущего шага.

Затем для столбца D выполните соединение, используя то, что не использовалось в столбцах A, B и C для каждого подмножества набора данных из предыдущего шага.

Так далее и тому подобное.

Вот реализация вышеупомянутой идеи в data.table:

v <- c(10, 20, 30, 40, 40)
nm <- names(dat)

dat <- dat[.(A=unique(v)), on=.(A), nomatch=0L]

for (k in seq_along(nm)[-1L]) {
    dat <- dat[, .SD[.(unique(v[-match(.BY, v)])), 
                     on=eval(nm[k]), 
                     nomatch=0L], 
        by=eval(nm[seq_len(k)[-k]])]
}
dat

вывод для v <- c(10, 20, 30, 40, 40):

    A  B  C  D  E
1: 10 40 40 20 30
2: 40 40 10 20 30
3: 40 40 10 20 30

вывод для v <- c(10, 20, 30, 40, 50):

    A  B  C  D  E
1: 30 10 20 50 40
2: 50 40 10 20 30

данные:

library(data.table)
dat <- fread("A  B  C  D  E  
1  5  7  19 2    
90 12 8  45 30
30 10 20 50 40
33 11 22 55 44
50 40 10 20 30
40 40 10 20 30  
40 40 10 20 30    
10 40 40 20 30")     #2 dupe rows to demonstrate edge case 

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