Подмножества строк со всеми/любыми столбцами, большими, чем определенное значение

С

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

Ответ 1

См. функции 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, если все элементы входного вектора 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 (как показано выше).

Ответ 2

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

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

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

df[apply(df, 1, function(row) {all(row > 10)}),]

Ответ 3

Один из вариантов - циклическая последовательность строк (например, с 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