2013-12-19 111 views
3

我有一个数据帧,其中变量是字符串。我怎样才能提取只有至少有一个值匹配特定字符串的列?例如,在下面的数据框中,我想要匹配字符串“AB”,即我想要将包含列V1,V2和V5的另一个数据框子集。R:通过字符串匹配提取数据帧的列

V1  V2  V3  V4  V5 
ABCD ABEF EFGJ AFASD JLKJLXKJ 
LKJAF ROGIJ GREJWI SDFS ABKLJKJX 
AFSD JLASDF JKLJ OIJPOI AFSD 
+2

使用grepl和sapply?你有什么尝试? – A5C1D2H2I1M1N2O1R2T1

+0

我不知道从哪里开始。我有389个变量。 – user702432

回答

5

首先,您可以用所需的模式应用grepl到每一列:

> sapply(data, function (x) grepl('AB', x)) 
     V1 V2 V3 V4 V5 
[1,] TRUE TRUE FALSE FALSE FALSE 
[2,] FALSE FALSE FALSE FALSE TRUE 
[3,] FALSE FALSE FALSE FALSE FALSE 

你可以通过包装grepl简化以上结果any

> sapply(data, function (x) any(grepl('AB', x))) 
    V1 V2 V3 V4 V5 
TRUE TRUE FALSE FALSE TRUE 

有了这样的载体,你可以方便地提取所需的列:

data[, sapply(data, function (x) any(grepl('AB', x)))] 

,其结果是:

 V1  V2  V5 
1 ABCD ABEF JLKJLXKJ 
2 LKJAF ROGIJ ABKLJKJX 
3 AFSD JLASDF  AFSD 
+0

完美。非常感谢,zero323。 – user702432

1

使用awk该打印列V1,V2和V5,如果塔V5包含AB

awk '$NF~"AB" {print $1,$2,$5}' OFS="\t" file 
LKJAF ROGIJ ABKLJKJX 
+0

问题显然标记为“r”。 – Roland

+2

我不知道'r'是什么,但'grep'是一个unix工具,'awk'的功能与'grep'相当。 – Jotne

+0

好点。我删除了错误的标签。 'grep'也是一个R函数。 – Roland

4

在这一点上,我的回答不会增加太多,但我当我发布评论时,我的手机就在我的手机上,所以我不愿意发布实际的答案。

无论如何,这是我会建议的。这几乎是相同的概念@ zero323的答案,但使用sapplyvapply代替apply,因为这些都可能是更有效的的data.frame列:

mydf[vapply(mydf, function(x) any(grepl("AB", x)), vector(length = 1))] 

mydf[sapply(mydf, function(x) any(grepl("AB", x)))] 

为了显示速度差异,让我们试试更大的data.frame,这是500行×500列。

library(microbenchmark) 
fun1a <- function() mydf[vapply(mydf, function(x) any(grepl("AB", x)), vector(length = 1))] 
fun1b <- function() mydf[sapply(mydf, function(x) any(grepl("AB", x)))] 
fun2 <- function() mydf[, apply(mydf, 2, function (x) any(grepl('AB', x)))] 

set.seed(1) 
nrow <- 500 
ncol <- 500 
x <- sample(8, nrow*ncol, replace = TRUE) 
y <- lapply(x, function(z) paste(sample(LETTERS, z, replace = TRUE), collapse = "")) 
mydf <- data.frame(matrix(unlist(y, use.names = FALSE), nrow = nrow)) 

microbenchmark(fun1a(), fun1b(), fun2(), times = 10) 
# Unit: milliseconds 
#  expr  min  lq median  uq  max neval 
# fun1a() 75.46204 82.84732 101.22437 115.8292 120.5349 10 
# fun1b() 75.92004 85.82025 99.31647 108.5303 310.0216 10 
# fun2() 134.82356 168.44435 182.88842 196.4751 207.9986 10 
identical(fun1a(), fun2()) 
# [1] TRUE 
identical(fun1b(), fun2()) 
# [1] TRUE 

vapply通常给出一个有点速度提升,但在这种情况下,似乎没有。

+0

非常令人印象深刻。很高兴知道,谢谢你的详细解释。 – user702432