2015-11-19 47 views
0

使用grepl讓我們假設我有以下變量:爲multipe文本

a <- c('one','two','three') 
b <- c('one|on','two|wo',"three|thre") 
c <- c('there is one','there one is ','there is one three two') 

而且我想,結果如下新的變量:

d 
[1] "one" "one" "three" 

我所試圖做的是找到例如文字oneon,然後將新值one分配給新變量d。此外,如果a中有多個值,則層次結構應該來自最後一個值。

什麼我可以做的是以下幾點:

d <- list() 
d[grepl(b[1],c)] <- a[1] 
d[grepl(b[2],c)] <- a[2] 
d[grepl(b[3],c)] <- a[3] 
d <- unlist(d) 

同樣可以在一個簡單的循環來完成。但有沒有其他更優雅的方式?

+0

你看過'stri_replace_all_regex'嗎? –

回答

0

這是不是所有的優雅,但這個功能你想要做什麼:

funny_replace <- function(c, b, a) { 

    max_or_null <- function(x) { 
     if (length(x) != 0) max(x) else NULL 
    } 

    multi_grep <- function(b, x) { 
     which(sapply(b, grepl, x)) 
    } 

    replace_one <- function(s, b, a) { 
     a[max_or_null(multi_grep(b, s))] 
    } 

    unlist(sapply(c, replace_one, b, a)) 
} 
funny_replace(c, b, a) 
#  there is one   there one is there is one three two 
#    "one"     "one"    "three" 

其工作原理如下:max_or_null用於返回一個向量的最大值或NULL,如果向量是空的。稍後用它來確保c的元素(b沒有匹配的模式)被正確處理。

multi_grep在單個字符串中搜索多個模式(通常grep做的相反:多個字符串中的一個模式)並返回找到的模式的索引。

replace_one取單個字符串並檢查b中哪些模式是使用multi_grep找到的。然後它使用max_or_null來返回這些索引中最大的索引,如果沒有匹配,則返回NULL。最後,具有該索引的元素從a中挑選。

replace_one然後應用於c的每個元素以獲得期望的結果。

我認爲,這是一個比你自己或for循環更有效的解決方案,因爲它避免了重複的分配。另一方面,它似乎有點複雜。

順便說一句:我用a,bc無處不在,使我的代碼更容易匹配你的例子。但是,這並不是很好的做法。

+0

我喜歡這個答案。但它有點不太可讀。我不喜歡的是它不會返回與輸入大小相同的大小。它只返回匹配輸入值的值。所以我通過添加兩行代替NULL來修改它。 (我刪除了未列出的行):結果< - as.character(sapply(c,replace_one,b,a));結果[Result =='character(0)] < - 不適用 –

+0

實際上,您的解決方案不會返回與輸入相同的大小,這就是爲什麼我按照自己的方式制定解決方案的原因。使用與輸入相同大小的輸出的一種簡單方法是用'max_or_null'中的'NaN'替換'NULL'(然後應該將它重命名爲'max_or_nan' ...)。這是有效的,因爲'[NaN]'是'NA'。 – Stibu

+0

它確實返回相同的大小。也許我不得不提到最後一行是'Result'來輸出整個向量。 –