Có một chức năng để đếm số lượng từ trong một chuỗi? Ví dụ:
str1 <- "How many words are in this sentence"
để trả về kết quả là 7.
Có một chức năng để đếm số lượng từ trong một chuỗi? Ví dụ:
str1 <- "How many words are in this sentence"
để trả về kết quả là 7.
Câu trả lời:
Bạn có thể sử dụng strsplit
và sapply
các chức năng
sapply(strsplit(str1, " "), length)
lengths
trong cơ sở R, hàm này tìm độ dài của mỗi phần tử:lengths(strsplot(str, " "))
Sử dụng biểu tượng cụm từ thông dụng \\W
để so khớp các ký tự không phải từ, dùng +
để chỉ một hoặc nhiều trong một hàng, cùng với đó gregexpr
để tìm tất cả các kết quả phù hợp trong một chuỗi. Các từ là số lượng ngăn cách từ cộng với 1.
lengths(gregexpr("\\W+", str1)) + 1
Điều này sẽ thất bại với chuỗi trống ở đầu hoặc cuối của vector nhân vật, khi một "từ" không đáp ứng \\W
's khái niệm phi-word (người ta có thể làm việc với các biểu thức thông thường khác, \\S+
, [[:alpha:]]
, vv, nhưng sẽ luôn là các trường hợp cạnh với cách tiếp cận regex), v.v. Nó có thể hiệu quả hơn strsplit
các giải pháp, sẽ phân bổ bộ nhớ cho mỗi từ. Biểu thức chính quy được mô tả trong ?regex
.
Cập nhật Như đã lưu ý trong các nhận xét và trong một câu trả lời khác của @Andri, cách tiếp cận không thành công với (không) và chuỗi một từ và với dấu câu ở cuối
str1 = c("", "x", "x y", "x y!" , "x y! z")
lengths(gregexpr("[A-z]\\W+", str1)) + 1L
# [1] 2 2 2 3 3
Nhiều câu trả lời khác cũng không thành công trong những trường hợp này hoặc tương tự (ví dụ: nhiều khoảng trắng). Tôi nghĩ rằng câu trả lời của tôi báo trước về 'khái niệm một từ' trong câu trả lời ban đầu bao gồm các vấn đề với dấu câu (giải pháp: chọn một biểu thức chính quy khác, ví dụ [[:space:]]+
:), nhưng trường hợp 0 và một từ là một vấn đề; Giải pháp của @ Andri không phân biệt được giữa 0 và 1 từ. Vì vậy, thực hiện một cách tiếp cận 'tích cực' để tìm các từ mà một người có thể
sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
Dẫn tới
sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
# [1] 0 1 2 2 3
Một lần nữa, biểu thức chính quy có thể được tinh chỉnh cho các khái niệm khác nhau về 'từ'.
Tôi thích việc sử dụng gregexpr()
vì nó hiệu quả về bộ nhớ. Một giải pháp thay thế bằng cách sử dụng strsplit()
(như @ user813966, nhưng với biểu thức chính quy để phân tách các từ) và sử dụng khái niệm ban đầu về phân tách các từ là
lengths(strsplit(str1, "\\W+"))
# [1] 0 1 2 2 3
Điều này cần phân bổ bộ nhớ mới cho mỗi từ được tạo và cho danh sách các từ trung gian. Điều này có thể tương đối tốn kém khi dữ liệu 'lớn', nhưng có lẽ nó hiệu quả và dễ hiểu cho hầu hết các mục đích.
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1
trả lại 4
và 8
. Đầu tiên đúng, thứ hai quá nhiều. Tôi nghĩ rằng nó đang đếm dấu câu.
sapply(gregexpr("\\W+", "word"), length) + 1
trả về 2
Cách đơn giản nhất sẽ là:
require(stringr)
str_count("one, two three 4,,,, 5 6", "\\S+")
... đếm tất cả các chuỗi trên các ký tự không phải khoảng trắng ( \\S+
).
Nhưng còn một hàm nhỏ cho phép chúng ta quyết định loại từ nào chúng ta muốn đếm và hoạt động trên cả vectơ thì sao?
require(stringr)
nwords <- function(string, pseudo=F){
ifelse( pseudo,
pattern <- "\\S+",
pattern <- "[[:alpha:]]+"
)
str_count(string, pattern)
}
nwords("one, two three 4,,,, 5 6")
# 3
nwords("one, two three 4,,,, 5 6", pseudo=T)
# 6
Tôi sử dụng str_count
hàm từ stringr
thư viện với trình tự thoát \w
đại diện:
bất kỳ ký tự 'từ' nào (chữ cái, chữ số hoặc dấu gạch dưới trong ngôn ngữ hiện tại: ở chế độ UTF-8, chỉ các chữ cái và chữ số ASCII mới được xem xét)
Thí dụ:
> str_count("How many words are in this sentence", '\\w+')
[1] 7
Trong tất cả 9 câu trả lời khác mà tôi có thể kiểm tra, chỉ có hai câu (của Vincent Zoonekynd, và của petermeissner) phù hợp với tất cả các đầu vào được trình bày ở đây cho đến nay, nhưng chúng cũng yêu cầu stringr
.
Nhưng chỉ giải pháp này hoạt động với tất cả các đầu vào được trình bày cho đến nay, cộng với các đầu vào như "foo+bar+baz~spam+eggs"
hoặc "Combien de mots sont dans cette phrase ?"
.
Điểm chuẩn:
library(stringr)
questions <-
c(
"", "x", "x y", "x y!", "x y! z",
"foo+bar+baz~spam+eggs",
"one, two three 4,,,, 5 6",
"How many words are in this sentence",
"How many words are in this sentence",
"Combien de mots sont dans cette phrase ?",
"
Day after day, day after day,
We stuck, nor breath nor motion;
"
)
answers <- c(0, 1, 2, 2, 3, 5, 6, 7, 7, 7, 12)
score <- function(f) sum(unlist(lapply(questions, f)) == answers)
funs <-
c(
function(s) sapply(gregexpr("\\W+", s), length) + 1,
function(s) sapply(gregexpr("[[:alpha:]]+", s), function(x) sum(x > 0)),
function(s) vapply(strsplit(s, "\\W+"), length, integer(1)),
function(s) length(strsplit(gsub(' {2,}', ' ', s), ' ')[[1]]),
function(s) length(str_match_all(s, "\\S+")[[1]]),
function(s) str_count(s, "\\S+"),
function(s) sapply(gregexpr("\\W+", s), function(x) sum(x > 0)) + 1,
function(s) length(unlist(strsplit(s," "))),
function(s) sapply(strsplit(s, " "), length),
function(s) str_count(s, '\\w+')
)
unlist(lapply(funs, score))
Đầu ra:
6 10 10 8 9 9 7 6 6 11
'[\\w\']+'
(không thể kiểm tra nó, vì vậy xkcd.com/1638 có thể áp dụng), nếu không, tôi không chắc liệu regex là đủ mạnh để xử lý nó trong trường hợp tổng quát :)
'\\w+(\'\\w{1,2})?'
có thể là một giải pháp tốt.
o'clock
và friggin'
bạn có thể làm \w+('\w*)?
(Tôi không biết liệu có những từ bắt đầu bằng dấu nháy đơn không?). Ngoài ra, để xử lý giờ, bạn có thể cố gắng khớp chúng như \d?\d:\d\d|\w+('\w*)?
hoặc làm một việc gì đó thậm chí phức tạp hơn tùy thuộc vào nhu cầu của bạn. Nhưng điều này ngày càng ít về R và nhiều hơn về cách bạn định nghĩa một từ, vì vậy có thể bạn có thể đăng một câu hỏi riêng để đáp ứng nhu cầu cụ thể của mình?
str2 <- gsub(' {2,}',' ',str1)
length(strsplit(str2,' ')[[1]])
Các gsub(' {2,}',' ',str1)
đảm bảo tất cả các từ được ngăn cách bởi chỉ có một không gian, bằng cách thay thế tất cả các lần xuất hiện của hai hay nhiều không gian với một không gian.
Phép strsplit(str,' ')
tách câu ở mọi khoảng trắng và trả về kết quả trong một danh sách. Các [[1]]
grabs vector các từ ra khỏi danh sách đó. Số length
đếm lên có bao nhiêu từ.
> str1 <- "How many words are in this sentence"
> str2 <- gsub(' {2,}',' ',str1)
> str2
[1] "How many words are in this sentence"
> strsplit(str2,' ')
[[1]]
[1] "How" "many" "words" "are" "in" "this" "sentence"
> strsplit(str2,' ')[[1]]
[1] "How" "many" "words" "are" "in" "this" "sentence"
> length(strsplit(str2,' ')[[1]])
[1] 7
Bạn có thể sử dụng str_match_all
, với một biểu thức chính quy sẽ xác định các từ của bạn. Phần sau hoạt động với các khoảng trống ban đầu, cuối cùng và các dấu cách trùng lặp.
library(stringr)
s <- "
Day after day, day after day,
We stuck, nor breath nor motion;
"
m <- str_match_all( s, "\\S+" ) # Sequences of non-spaces
length(m[[1]])
Hãy thử chức năng này từ stringi
gói
require(stringi)
> s <- c("Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
+ "nibh augue, suscipit a, scelerisque sed, lacinia in, mi.",
+ "Cras vel lorem. Etiam pellentesque aliquet tellus.",
+ "")
> stri_stats_latex(s)
CharsWord CharsCmdEnvir CharsWhite Words Cmds Envirs
133 0 30 24 0 0
Bạn có thể loại bỏ khoảng trắng kép và đếm số lượng " "
trong chuỗi để có được số lượng từ. Sử dụng stringr và rm_white
{ qdapRegex }
str_count(rm_white(s), " ") +1
Giải pháp 7 không đưa ra kết quả chính xác trong trường hợp chỉ có một từ. Bạn không nên chỉ đếm các phần tử trong kết quả của gregexpr (là -1 nếu ở đó không khớp) mà hãy đếm các phần tử> 0.
Ergo:
sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1
str1
bắt đầu hoặc kết thúc bằng các ký tự không phải từ. Nếu đó là một mối quan tâm, phiên bản này sẽ chỉ tìm kiếm khoảng trống giữa chữ:sapply(gregexpr("\\b\\W+\\b", str, perl=TRUE), function(x) sum(x>0) ) + 1
Tôi đã tìm thấy hàm sau và regex hữu ích cho việc đếm từ, đặc biệt là trong việc xử lý dấu gạch nối đơn so với dấu gạch nối kép, trong đó dấu gạch ngang trước đây thường không được tính là ngắt từ, ví dụ: nổi tiếng, hi-fi; trong khi dấu gạch ngang kép là dấu phân cách dấu câu không bị giới hạn bởi khoảng trắng - chẳng hạn như đối với nhận xét trong ngoặc đơn.
txt <- "Don't you think e-mail is one word--and not two!" #10 words
words <- function(txt) {
length(attributes(gregexpr("(\\w|\\w\\-\\w|\\w\\'\\w)+",txt)[[1]])$match.length)
}
words(txt) #10 words
Stringi là một gói hữu ích. Nhưng nó đếm quá số từ trong ví dụ này do dấu gạch nối.
stringi::stri_count_words(txt) #11 words
Với gói stringr , người ta cũng có thể viết một tập lệnh đơn giản có thể duyệt một vectơ chuỗi chẳng hạn thông qua vòng lặp for.
Hãy cùng nói nào
df $ text
chứa một vectơ của các chuỗi mà chúng tôi muốn phân tích. Đầu tiên, chúng tôi thêm các cột bổ sung vào df dataframe hiện có như sau:
df$strings = as.integer(NA)
df$characters = as.integer(NA)
Sau đó, chúng tôi chạy vòng lặp for trên vectơ chuỗi như bên dưới:
for (i in 1:nrow(df))
{
df$strings[i] = str_count(df$text[i], '\\S+') # counts the strings
df$characters[i] = str_count(df$text[i]) # counts the characters & spaces
}
Các cột kết quả: chuỗi và ký tự sẽ chứa số lượng từ và ký tự và điều này sẽ đạt được chỉ trong một lần đối với một vectơ chuỗi.