R中的子集多列 - 更优雅的代码?

时间:2012-03-09 21:49:05

标签: r subset

我根据多个列的多个条件对数据帧进行子集化。我选择数据框中的行,这些行包含在三个不同列中的任何一列中的矢量“criteria”中定义的几个值中的任何一个。

我有一些有用的代码,但是想知道其他(更优雅?)的方法是做什么的。这就是我所做的:

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

建议热烈欢迎。 (我是R初学者,所以对你所建议的非常简单的解释也受到热烈欢迎。)

2 个答案:

答案 0 :(得分:13)

我不确定您是否需要两次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) 

答案 1 :(得分:6)

我使用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

测试一行中的任何值是否为TRUE

> 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