строки подмножества со всеми / любыми столбцами больше определенного значения - PullRequest
14 голосов
/ 25 марта 2012

С

df <- data.frame(id=c(1:5), v1=c(0,15,9,12,7), v2=c(9,32,6,17,11))

Как извлечь строки со значениями во ВСЕХ столбцах больше 10, которые должны вернуть:

  id v1 v2
2  2 15 32
4  4 12 17

А что если в ЛЮБОМ столбце больше 10:

  id v1 v2
2  2 15 32
4  4 12 17
5  5  7 11

Ответы [ 3 ]

19 голосов
/ 25 марта 2012

См. Функции all() и any() для первой и второй частей ваших вопросов соответственно. Функция apply() может использоваться для запуска функций над строками или столбцами. (MARGIN = 1 - строки, MARGIN = 2 - столбцы и т. Д.). Примечание. Я использую apply() для df[, -1], чтобы игнорировать переменную id при сравнении.

Часть 1:

> df <- data.frame(id=c(1:5), v1=c(0,15,9,12,7), v2=c(9,32,6,17,11))
> df[apply(df[, -1], MARGIN = 1, function(x) all(x > 10)), ]
  id v1 v2
2  2 15 32
4  4 12 17

Часть 2:

> df[apply(df[, -1], MARGIN = 1, function(x) any(x > 10)), ]
  id v1 v2
2  2 15 32
4  4 12 17
5  5  7 11

Чтобы увидеть, что происходит, x > 10 возвращает логический вектор для каждой строки (через apply(), указывающий, больше ли каждый элемент 10. all() возвращает TRUE, если all element вектора ввода TRUE и FALSE в противном случае. any() возвращает TRUE, если любой элементов на входе равен TRUE и FALSE, если все FALSE.

Затем я использую логический вектор, полученный в результате apply() вызова

> apply(df[, -1], MARGIN = 1, function(x) all(x > 10))
[1] FALSE  TRUE FALSE  TRUE FALSE
> apply(df[, -1], MARGIN = 1, function(x) any(x > 10))
[1] FALSE  TRUE FALSE  TRUE  TRUE

в подмножество df (как показано выше).

6 голосов
/ 25 марта 2012

Это можно сделать с помощью apply с полем 1, которое будет применять функцию к каждой строке.Функция для проверки данной строки будет

function(row) {all(row > 10)}

Таким образом, способ извлечения самих строк -

df[apply(df, 1, function(row) {all(row > 10)}),]
2 голосов
/ 11 августа 2017

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

Векторизованный подход заключается в использовании rowSums для определения количества значений в каждой строке, соответствующей вашему критерию, и фильтрации на основе этого.

При фильтрации по строкам, где все равно не менее 10, это аналогично фильтрации по случаям, когда число значений не более 10 равно 0:

df[rowSums(df[,-1] <= 10) == 0,]
#   id v1 v2
# 2  2 15 32
# 4  4 12 17

Аналогично, rowSums может быть легкоиспользуется для вычисления строк с чем-либо, превышающим 10:

df[rowSums(df[,-1] > 10) > 0,]
#   id v1 v2
# 2  2 15 32
# 4  4 12 17
# 5  5  7 11

Ускорение ясно с большим вводом:

set.seed(144)
df <- matrix(sample(c(1, 10, 20), 3e6, replace=TRUE), ncol=3)
system.time(df[apply(df[, -1], MARGIN = 1, function(x) all(x > 10)), ])
#    user  system elapsed 
#   1.754   0.156   2.102 
system.time(df[rowSums(df[,-1] <= 10) == 0,])
#    user  system elapsed 
#    0.04    0.01    0.05 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...