Подмножество нескольких столбцов в R - более элегантный код? - PullRequest
5 голосов
/ 10 марта 2012

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

У меня есть некоторый код, который работает, но интересно, что другое (более элегантно?) Есть способы сделать это.Вот что я сделал:

criteria <-c(1:10)
subset1 <-subset(data, data[, "Col1"] %in% criteria | data[, "Col2"]
 %in% criteria | data[, "Col3"] %in% criteria)

Предложения горячо приветствуются.(Я начинающий R, поэтому очень простые объяснения того, что вы предлагаете, также горячо приветствуются.)

Ответы [ 2 ]

13 голосов
/ 10 марта 2012

Я не уверен, что вам нужно два apply вызова здесь:

# Data
df=data.frame(x=1:4,Col1=c(11,12,3,13),Col2=c(9,12,10,13),Col3=c(9,13,42,23))
criteria=1:10

# Solution
df[apply(df [c('Col1','Col2','Col3')],1,function(x) any(x %in% criteria)),]

Если вы не хотите использовать много столбцов, тогда, вероятно, будет более читабельно сказать:

subset(df, Col1 %in% criteria | Col2 %in% criteria | Col3 %in% criteria) 
6 голосов
/ 10 марта 2012

Я использую DF вместо data в качестве примера.

DF[apply(apply(as.matrix(DF[c("Col1","Col2","Col3")]), 
               c(1,2), `%in%`, criteria), 
         1, any),]

Для разбивки того, что это делает:

Составьте матрицу из указанных столбцови для каждого элемента в этом тесте матрицы, если он содержит один из критериев.Затем для каждой строки этой матрицы посмотрите, являются ли какие-либо элементы строки TRUE.Если это так, сохраните соответствующую строку исходного набора данных.

Работа с примером:

Начните с фиктивных данных:

DF <- data.frame(Col1=seq(1, by=2, length=10),
                 Col2=seq(3, by=3, length=10),
                 Col3=seq(7, by=1, length=10),
                 other=LETTERS[1:10])

, который выглядит как

> DF
   Col1 Col2 Col3 other
1     1    3    7     A
2     3    6    8     B
3     5    9    9     C
4     7   12   10     D
5     9   15   11     E
6    11   18   12     F
7    13   21   13     G
8    15   24   14     H
9    17   27   15     I
10   19   30   16     J

Вытащите только интересующие столбцы.

> as.matrix(DF[c("Col1","Col2","Col3")])
      Col1 Col2 Col3
 [1,]    1    3    7
 [2,]    3    6    8
 [3,]    5    9    9
 [4,]    7   12   10
 [5,]    9   15   11
 [6,]   11   18   12
 [7,]   13   21   13
 [8,]   15   24   14
 [9,]   17   27   15
[10,]   19   30   16

Проверьте каждую запись по критерию

> apply(as.matrix(DF[c("Col1","Col2","Col3")]), c(1,2), `%in%`, criteria)
       Col1  Col2  Col3
 [1,]  TRUE  TRUE  TRUE
 [2,]  TRUE  TRUE  TRUE
 [3,]  TRUE  TRUE  TRUE
 [4,]  TRUE FALSE  TRUE
 [5,]  TRUE FALSE FALSE
 [6,] FALSE FALSE FALSE
 [7,] FALSE FALSE FALSE
 [8,] FALSE FALSE FALSE
 [9,] FALSE FALSE FALSE
[10,] FALSE FALSE FALSE

Проверьте, являются ли какие-либо из значений в строке ИСТИНА

> apply(apply(as.matrix(DF[c("Col1","Col2","Col3")]), c(1,2), `%in%`, criteria), 1, any)
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE

Используйте это для индексации исходного фрейма данных.

> DF[apply(apply(as.matrix(DF[c("Col1","Col2","Col3")]), c(1,2), `%in%`, criteria), 1, any),]
  Col1 Col2 Col3 other
1    1    3    7     A
2    3    6    8     B
3    5    9    9     C
4    7   12   10     D
5    9   15   11     E
...