2017-02-22 43 views
2

我有一个数据帧,看起来像这样之间的空间只有行:过滤器[R数据帧以包括两个字符串

v1 <- c('abies balsamifera','some trees','pizza','i like tacos','pinus taeda') 
v2 <- c(1,2,3,4,5) 
data <- data.frame(v1,v2) 
       v1 v2 
1 abies balsamifera 1 
2  some trees 2 
3    pizza 3 
4  i like tacos 4 
5  pinus taeda 5 

我想子集数据框,只有包括行,其中在v1的字符串有两个单词用空格隔开。我想要排除只包含一个单词的行或包含三个单词的其他行。所得到的数据帧是这样的:

    v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

回答

7

你正在寻找一个是由一个或多个单词字符,一个空格,再一个或多个单词字符的字符串。

这里是一个正则表达式,它描述了上述声明:

> grepl('^\\w+\\s\\w+$', v1) 
[1] TRUE TRUE FALSE FALSE TRUE 

你可以用这个逻辑向量索引数据帧。

3

一种替代方法计算空格的数量,允许多个相邻空间(例如,数据输入错字)的可能性。

data[sapply(gregexpr(" +", data$v1), function(i) sum(i > 0)) == 1, ] 
       v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

gregexpr读取通过字符向量,并返回compsed匹配的字符向量的每个元素的位置的矢量的列表。给出非匹配(-1),因此每个值都与0相比较,然后相加。有一个匹配的值(一组相邻空格字符)返回TRUE。 sapply用于通读列表并返回一个向量。

1

以下是使用strsplit()的解决方案。请注意,由于它使用循环,所以速度可能会更慢。

v1 <- c('abies balsamifera','some trees','pizza','i like tacos','pinus taeda') 
v2 <- c(1,2,3,4,5) 
data <- data.frame(v1,v2) 
colnames(data) <- c("v1", "v2") 

spacer <- function(data){ 
    booleans <- vector() 
    i <- 1 
    while (i <= nrow(data)){ 
     tmp <- strsplit(as.character(data$v1[i]), ' ')[[1]] 
     booleans[i] <- (length(tmp) == 2) 
     i <- i + 1 
    } 
    return(res[(booleans),]) 
} 

data <- spacer(data) 

输出:

    v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

注:上面的代码编辑为提高可读性和功能与欢迎建议从@MatthewLundberg

+1

您可以简化代码,使其更具可读性。首先,不是'if'语句,而是直接赋值:'booleans [i] < - length(tmp)== 2'。其次,没有理由将'booleans'向量绑定到数据框,只需在函数的最后一个'return'行中删除'res $'。然后,您不需要通过分配NULL来删除该列。第三,作为一个单独的问题,您可以创建'booleans'向量,使其具有正确的长度,因为您知道它将成长为'数据'元素。 –

+0

@MatthewLundberg感谢代码审查 - 我很快就写了这段代码来获得答案(我正在使用它来尝试成为一个更好的程序员),但是我后来看到它,并注意到很多不必要的操作。我会用你的建议。我非常感谢你的时间! –