2017-02-22 88 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感謝代碼審查 - 我很快就寫了這段代碼來獲得答案(我正在使用它來嘗試成爲一個更好的程序員),但是我後來看到它,並注意到很多不必要的操作。我會用你的建議。我非常感謝你的時間! –