2012-03-02 23 views
26

Trong R, grep thường khớp với vectơ của nhiều chuỗi dựa vào một regexp.R grep: Ghép một chuỗi với nhiều mẫu

Hỏi: Có khả năng khớp một chuỗi đơn với nhiều regexps không? (không lặp qua từng mẫu regexp đơn)?

Một số nền:

Tôi có 7000+ từ khóa như các chỉ số cho một số chuyên mục. Tôi không thể thay đổi từ điển từ khóa đó. Từ điển có cấu trúc sau (các từ khóa trong col 1, các con số cho thấy các danh mục mà các từ khóa này thuộc về):

ab 10 37 41 
abbrach* 38 
abbreche 39 
abbrich* 39 
abend* 37 
abendessen* 60 63 
aber 20 23 45 
abermals 37 

Ghép nhiều từ khóa bằng "|" không phải là cách khả thi (và tôi sẽ không biết từ khóa nào tạo ra lần truy cập). Ngoài ra, chỉ cần đảo ngược "mẫu" và "chuỗi" không hoạt động, vì các mẫu có cắt cụt, sẽ không hoạt động theo cách khác.

[related question, ngôn ngữ lập trình khác]

+2

tôi như đề xuất của dan nhưng với một tập dữ liệu lớn, bạn có thể gặp phải một số vấn đề tốc độ đáng kể. Nếu bạn muốn tìm một cái gì đó trong một từ điển và trả về một giá trị tương ứng, tôi sẽ đề xuất một cách tiếp cận khác: Chia các câu thành vectơ của các từ riêng lẻ với strsplit và sau đó áp dụng một bảng băm để tra cứu nhanh. Tôi nghĩ rằng bạn có thể muốn ngắt từ khóa và các chỉ mục danh mục thành hai cột riêng biệt trong từ điển. Tôi sẽ cung cấp hỗ trợ ở đó nhưng chỉ sau khi bạn rõ ràng hơn về muốn là kết quả cuối cùng. –

+0

Đồng ý về việc tái cơ cấu dữ liệu từ điển và sử dụng bảng băm để tra cứu (tùy thuộc vào kết quả mong muốn), nhưng kết quả khớp sẽ tương đối nhanh tùy thuộc vào số lượng chuỗi, ngay cả với số lượng từ khóa lớn. Tôi sẽ thêm điểm chuẩn nhanh vào câu trả lời của mình. – danpelota

+1

Nếu bạn thực sự có nhiều từ (thông thường, tất cả các từ trong ngôn ngữ của con người, tất cả các từ được Google lập chỉ mục, v.v.), bạn có thể sử dụng [cây tiền tố] (http: // vi. wikipedia.org/wiki/Trie) (đôi khi còn được gọi là "trie"). Nhưng tôi không biết thực hiện bất kỳ trong R. –

Trả lời

28

gì về việc áp dụng các chức năng regexpr qua một vector từ khóa không?

keywords <- c("dog", "cat", "bird") 

strings <- c("Do you have a dog?", "My cat ate by bird.", "Let's get icecream!") 

sapply(keywords, regexpr, strings, ignore.case=TRUE) 

    dog cat bird 
[1,] 15 -1 -1 
[2,] -1 4 15 
[3,] -1 -1 -1 

    sapply(keywords, regexpr, strings[1], ignore.case=TRUE) 

dog cat bird 
    15 -1 -1 

Giá trị được trả lại là vị trí của ký tự đầu tiên trong trận đấu, với -1 có nghĩa là không khớp.

Nếu vị trí của trận đấu là không thích hợp, sử dụng grepl thay vì:

sapply(keywords, grepl, strings, ignore.case=TRUE) 

     dog cat bird 
[1,] TRUE FALSE FALSE 
[2,] FALSE TRUE TRUE 
[3,] FALSE FALSE FALSE 

Cập nhật: này chạy khá nhanh trên hệ thống của tôi, ngay cả với một số lượng lớn các từ khóa:

# Available on most *nix systems 
words <- scan("/usr/share/dict/words", what="") 
length(words) 
[1] 234936 

system.time(matches <- sapply(words, grepl, strings, ignore.case=TRUE)) 

    user system elapsed 
    7.495 0.155 7.596 

dim(matches) 
[1]  3 234936 
+0

Cảm ơn câu trả lời của bạn và ý kiến ​​của bạn! Cuối cùng, tôi đã làm một cách tiếp cận kết hợp: một trie giảm tập hợp các kết quả phù hợp với ~ 5% kích thước ban đầu, và hàm sapply đã làm grep. –

+0

Và sau đó để xem có bao nhiêu từ khóa khớp với mỗi câu/chuỗi, trên khung dữ liệu cuối cùng, vấn đề: num.matches <- áp dụng (dữ liệu.frame (kết hợp), 1, hàm (z) sum (z == TRUE)) . Và để tra cứu chuỗi gốc nào, giả sử, 2 kết quả phù hợp, phát hành: chuỗi [num.matches == 2] # Kết quả: [1] "Mèo của tôi đã ăn chim". –

+0

Điều gì sẽ xảy ra nếu bạn muốn thay thế, nơi bạn không chỉ đọc từ khóa để tìm kiếm mà còn phải thay thế từ khóa? – user1603472

2

Để mở rộng trên other answer, để chuyển đổi đầu ra sapply() thành một vectơ logic hữu ích, bạn cần sử dụng thêm bước apply().

keywords <- c("dog", "cat", "bird") 
strings <- c("Do you have a dog?", "My cat ate by bird.", "Let's get icecream!") 
(matches <- sapply(keywords, grepl, strings, ignore.case=TRUE)) 
#  dog cat bird 
# [1,] TRUE FALSE FALSE 
# [2,] FALSE TRUE TRUE 
# [3,] FALSE FALSE FALSE 

Để biết được chuỗi chứa bất kỳ các từ khóa (mẫu):

apply(matches, 1, any) 
# [1] TRUE TRUE FALSE 

Để biết được những từ khóa (mô hình) được xuất hiện trong chuỗi cung cấp:

apply(matches, 2, any) 
# dog cat bird 
# TRUE TRUE TRUE 
Các vấn đề liên quan