2015-11-22 32 views
6

Tôi đoán đây là vấn đề phổ biến và tôi tìm thấy khá nhiều trang web, bao gồm một số từ SO, nhưng tôi không hiểu cách triển khai.REGEX trong R: trích xuất các từ từ một chuỗi

Tôi mới dùng REGEX và tôi muốn sử dụng nó trong R để trích xuất một vài từ đầu tiên từ một câu.

ví dụ, nếu câu của tôi là

z = "I love stack overflow it is such a cool site" 

id muốn có đầu ra của tôi như là (nếu tôi cần bốn chữ đầu tiên)

[1] "I love stack overflow" 

hoặc (nếu tôi cần cuối bốn Nói cách)

[1] "such a cool site" 

tất nhiên, các công việc sau

paste(strsplit(z," ")[[1]][1:4],collapse=" ") 
paste(strsplit(z," ")[[1]][7:10],collapse=" ") 

nhưng tôi muốn thử một giải pháp regex cho vấn đề hiệu suất như tôi cần phải đối phó với các tập tin rất lớn (và cũng vì lợi ích của việc biết về nó)

Tôi nhìn một số liên kết, bao gồm Regex to extract first 3 words from a stringhttp://osherove.com/blog/2005/1/7/using-regex-to-return-the-first-n-words-in-a-string.html

vì vậy tôi cố gắng những thứ như

gsub("^((?:\S+\s+){2}\S+).*",z,perl=TRUE) 
Error: '\S' is an unrecognized escape in character string starting ""^((?:\S" 

tôi đã cố gắng cụ khác, nhưng nó thường trở lại tôi hoặc toàn bộ chuỗi hoặc chuỗi rỗng.

một vấn đề khác với chất nền là nó trả về một danh sách. có lẽ nó trông giống như các nhà điều hành [[]] là làm chậm những thứ một chút (??) khi giao dịch với các tập tin lớn và làm công cụ áp dụng.

có vẻ như Cú pháp được sử dụng trong R hơi khác một chút? cảm ơn!

+2

Bạn cần sử dụng thoát kép trong regex R. '\ S' ->' \\ S' –

+0

Bạn cũng có thể thử 'stringi :: stri_extract_all_words (z) [[1]] [1: 4]' dễ sử dụng hơn và không đòi hỏi phải biết regex. Mặc dù bạn sẽ nhận được các từ một giá trị riêng biệt. –

+0

Bạn không thể sử dụng cùng một ý tưởng mà tôi đã chia sẻ [trong câu hỏi trước đó của bạn] (http://stackoverflow.com/questions/33785594/manipulate-char-vectors-inside-a-data-table-object-in -r)? Bạn chỉ cần tăng gấp đôi các dấu gạch chéo ngược của bạn trong R, như đã được chỉ ra bởi @stribizhev. – A5C1D2H2I1M1N2O1R2T1

Trả lời

5

Bạn đã chấp nhận câu trả lời nhưng tôi sẽ chia sẻ câu trả lời này nhằm giúp bạn hiểu thêm một chút về regex trong R, vì bạn thực sự rất gần nhận câu trả lời sở hữu.


Có hai vấn đề với cách tiếp cận gsub của bạn:

  1. Bạn sử dụng những dấu xồ nguợc đơn (\). R yêu cầu bạn thoát khỏi chúng vì chúng là các ký tự đặc biệt. Bạn thoát chúng bằng cách thêm một dấu gạch chéo ngược khác (\\). Nếu bạn làm nchar("\\"), bạn sẽ thấy rằng nó trả về "1".

  2. Bạn không chỉ định thay thế sẽ là gì. Ở đây, chúng tôi không muốn thay thế bất cứ điều gì, nhưng chúng tôi muốn nắm bắt một phần cụ thể của chuỗi.Bạn chụp các nhóm trong ngoặc đơn (...) và sau đó bạn có thể tham chiếu nhóm theo số nhóm. Ở đây, chúng tôi chỉ có một nhóm, vì vậy chúng tôi gọi nó là "\\1".

Bạn nên đã cố gắng một cái gì đó như:

sub("^((?:\\S+\\s+){2}\\S+).*", "\\1", z, perl = TRUE) 
# [1] "I love stack" 

này về cơ bản đang nói:

  • làm việc từ khi bắt đầu các nội dung của "z".
  • Bắt đầu tạo nhóm 1.
  • Tìm phi khoảng trắng (như một từ) tiếp theo là khoảng trắng (\S+\s+) hai lần {2} và sau đó là tập tiếp theo của phi khoảng trắng (\S+). Điều này sẽ giúp chúng ta có 3 từ, mà không cần nhận khoảng trắng sau từ thứ ba. Do đó, nếu bạn muốn có một số từ khác nhau, hãy thay đổi {2} thành một số nhỏ hơn số bạn thực sự sau đó.
  • Kết thúc nhóm 1 ở đó.
  • Sau đó, chỉ cần trả lại nội dung của nhóm 1 (\1) từ "z".

Để có được ba chữ cuối cùng, chỉ cần chuyển vị trí của các nhóm chụp và đặt nó ở phần cuối của mô hình để phù hợp.

sub("^.*\\s+((?:\\S+\\s+){2}\\S+)$", "\\1", z, perl = TRUE) 
# [1] "a cool site" 
+0

cảm ơn. @Ananda Mahto. bạn có thể cung cấp cho regex cho 4 từ cuối cùng bằng cách sử dụng cùng một chức năng 'phụ'? –

+1

@FaguiCurtain, tôi chỉ hoán đổi các tham chiếu từ cố định đến đầu của dòng để kết thúc thay vào đó, như: '^. * ((?: \\ S + \\ s +) {2} \\ S +) $'. Thay đổi "2" thành "3" để nhận 4 từ thay vì 3. – A5C1D2H2I1M1N2O1R2T1

3

Để nhận được bốn từ đầu tiên.

library(stringr) 
str_extract(x, "^\\s*(?:\\S+\\s+){3}\\S+") 

Để nhận được số cuối cùng.

str_extract(x, "(?:\\S+\\s+){3}\\S+(?=\\s*$)") 
+0

hoặc 'phụ ("^\\ s * ((?: \\ S + \\ s +) {3} \\ S +) . * "," \\ 1 ", x)' –

+0

bạn có thể cho tôi đúng regex bằng cách sử dụng hàm 'sub'. tôi thực hiện một thử nghiệm trên một mẫu 10.000 và chức năng 'phụ' từ cơ sở R là nhanh hơn 30 lần so với' str_extract' từ 'thư viện (stringr)'. thanks –

+0

Tôi ngu ngốc nhưng không biết cách tinh chỉnh chức năng. 'sub (" (?: \\ S + \\ s +) {3} \\ S + (? = \\ s * $) ", thay thế =" ", z, perl = TRUE)' đang trả lại cho tôi '" Tôi yêu ngăn xếp tràn nó là "' là tất cả mọi thứ NHƯNG 4 từ cuối cùng ... –

Các vấn đề liên quan