Czy istnieje funkcja licząca liczbę słów w ciągu? Na przykład:
str1 <- "How many words are in this sentence"
aby zwrócić wynik 7.
r
string
word-count
Jan
źródło
źródło
Odpowiedzi:
Możesz używać
strsplit
isapply
funkcjisapply(strsplit(str1, " "), length)
źródło
lengths
funkcji w bazie R, która znajduje długość każdego elementu:lengths(strsplot(str, " "))
Użyj symbolu wyrażenia regularnego,
\\W
aby dopasować znaki niebędące słowami, użyj,+
aby wskazać jeden lub więcej w wierszu, a także,gregexpr
aby znaleźć wszystkie dopasowania w ciągu. Słowa to liczba separatorów słów plus 1.lengths(gregexpr("\\W+", str1)) + 1
To nie z pustymi strunami na początku lub na końcu wektora znaków, gdy „Słowo” nie spełnia
\\W
„s pojęcie nie-słowa (można pracować z innych wyrażeń regularnych\\S+
,[[:alpha:]]
itp, ale nie będzie zawsze być skrajnymi przypadkami z podejściem regex), itp. Prawdopodobnie jest bardziej wydajne niżstrsplit
rozwiązania, które przydzielą pamięć dla każdego słowa. Wyrażenia regularne opisano w?regex
.Aktualizacja Jak zauważono w komentarzach i w innej odpowiedzi @Andri, podejście kończy się niepowodzeniem z ciągami (zero) i jednowyrazowymi oraz z końcową interpunkcją
str1 = c("", "x", "x y", "x y!" , "x y! z") lengths(gregexpr("[A-z]\\W+", str1)) + 1L # [1] 2 2 2 3 3
Wiele innych odpowiedzi również zawodzi w tych lub podobnych przypadkach (np. Wiele spacji). Myślę, że moje zastrzeżenie dotyczące „pojęcia jednego słowa” w pierwotnej odpowiedzi obejmuje problemy z interpunkcją (rozwiązanie: wybierz inne wyrażenie regularne, np.
[[:space:]]+
), Ale problemem są przypadki z zerami i jednym słowem; Rozwiązanie @ Andri nie rozróżnia między zerem a jednym słowem. Można więc przyjąć „pozytywne” podejście do znajdowania słówsapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
Prowadzący do
sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0)) # [1] 0 1 2 2 3
Ponownie wyrażenie regularne można by udoskonalić pod kątem różnych pojęć „słowo”.
Podoba mi się użycie,
gregexpr()
ponieważ jest wydajne pod względem pamięci. Alternatywą jest używaniestrsplit()
(jak @ user813966, ale z wyrażeniem regularnym do oddzielania słów) i używanie oryginalnego pojęcia rozdzielania słówlengths(strsplit(str1, "\\W+")) # [1] 0 1 2 2 3
To wymaga przydzielenia nowej pamięci dla każdego tworzonego słowa i dla pośredniej listy słów. Może to być stosunkowo kosztowne, gdy dane są „duże”, ale prawdopodobnie jest skuteczne i zrozumiałe w większości zastosowań.
źródło
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1
zwroty4
i8
. Pierwsza poprawna, druga za dużo. Myślę, że liczy się interpunkcja.sapply(gregexpr("\\W+", "word"), length) + 1
zwraca 2Najprostszy sposób to:
require(stringr) str_count("one, two three 4,,,, 5 6", "\\S+")
... licząc wszystkie sekwencje na znaki inne niż spacje (
\\S+
).Ale co z małą funkcją, która pozwala nam również zdecydować, które rodzaje słów chcielibyśmy policzyć i która działa również na całych wektorach ?
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
źródło
Używam
str_count
funkcji zstringr
biblioteki z sekwencją ucieczki,\w
która reprezentuje:Przykład:
> str_count("How many words are in this sentence", '\\w+') [1] 7
Ze wszystkich pozostałych 9 odpowiedzi, które udało mi się przetestować, tylko dwie (autorstwa Vincenta Zoonekynda i Petermeissnera) działały dla wszystkich przedstawionych dotychczas danych wejściowych, ale one również wymagają
stringr
.Ale tylko to rozwiązanie działa ze wszystkimi dotychczas przedstawionymi danymi wejściowymi oraz wejściami takimi jak
"foo+bar+baz~spam+eggs"
lub"Combien de mots sont dans cette phrase ?"
.Reper:
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))
Wynik:
6 10 10 8 9 9 7 6 6 11
źródło
'[\\w\']+'
(nie można tego przetestować, więc xkcd.com/1638 może mieć zastosowanie), w przeciwnym razie nie jestem pewien, czy regex jest wystarczająco potężny, aby sobie z tym poradzić w ogólnym przypadku :)'\\w+(\'\\w{1,2})?'
może to być dobre rozwiązanie.o'clock
ifriggin'
możesz to zrobić\w+('\w*)?
(nie wiem, czy są słowa zaczynające się od apostrofu?). Aby dodatkowo obsłużyć godziny, możesz spróbować je dopasować\d?\d:\d\d|\w+('\w*)?
lub zrobić coś jeszcze bardziej skomplikowanego w zależności od potrzeb. Ale coraz mniej dotyczy to języka R, a więcej dotyczy tego, jak definiujesz słowo, więc może możesz zadać osobne pytanie, aby zaspokoić swoje konkretne potrzeby?str2 <- gsub(' {2,}',' ',str1) length(strsplit(str2,' ')[[1]])
Te
gsub(' {2,}',' ',str1)
marki, że wszystkie słowa są oddzielone tylko jednej przestrzeni, poprzez zastąpienie wszystkich wystąpień dwóch lub więcej pomieszczeń z jednego miejsca.strsplit(str,' ')
Dzieli zdanie w każdej przestrzeni i zwraca wynik w postaci listy.[[1]]
Chwyta wektor słów z tej listy.length
Liczy się jak najwięcej słów.> 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
źródło
Możesz użyć
str_match_all
, z wyrażeniem regularnym, które identyfikowałoby twoje słowa. Poniższe informacje dotyczą spacji początkowych, końcowych i powielonych.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]])
źródło
Wypróbuj tę funkcję z
stringi
pakieturequire(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
źródło
Możesz użyć funkcji wc w bibliotece qdap :
> str1 <- "How many words are in this sentence" > wc(str1) [1] 7
źródło
Możesz usunąć podwójne spacje i policzyć liczbę
" "
w ciągu, aby uzyskać liczbę słów. Użyj stringr irm_white
{ qdapRegex }str_count(rm_white(s), " ") +1
źródło
Spróbuj tego
length(unlist(strsplit(str1," ")))
źródło
Również z
stringi
pakietu, prosta funkcjastri_count_words
stringi::stri_count_words(str1) #[1] 7
źródło
Rozwiązanie 7 nie daje prawidłowego wyniku w przypadku, gdy jest tylko jedno słowo. Powinieneś nie tylko liczyć elementy w wyniku gregexpr (czyli -1, jeśli tam, gdzie nie pasuje), ale policzyć elementy> 0.
Ergo:
sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1
źródło
str1
zaczyna się lub kończy znakami niebędącymi słowami. Jeśli to dotyczy, ta wersja będzie szukać tylko spacji między słowami:sapply(gregexpr("\\b\\W+\\b", str, perl=TRUE), function(x) sum(x>0) ) + 1
require(stringr) str_count(x,"\\w+")
będzie dobrze z podwójnymi / potrójnymi odstępami między słowami
We wszystkich innych odpowiedziach występuje więcej niż jedna spacja między wyrazami.
źródło
wymagają (stringr)
Zdefiniuj bardzo prostą funkcję
str_words <- function(sentence) { str_count(sentence, " ") + 1 }
Czek
źródło
Posługiwać się
nchar
jeśli wywoływany jest wektor ciągów
x
(nchar(x) - nchar(gsub(' ','',x))) + 1
Sprawdź liczbę spacji, a następnie dodaj jedną
źródło
Zauważyłem, że następująca funkcja i wyrażenie regularne są przydatne do liczenia słów, zwłaszcza w przypadku łączników pojedynczych i podwójnych, gdzie ta pierwsza generalnie nie powinna być liczona jako podział wyrazu, np. Dobrze znane, hi-fi; podczas gdy podwójny łącznik jest separatorem interpunkcyjnym, który nie jest ograniczony białymi znakami - na przykład w przypadku uwag w nawiasach.
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 to przydatny pakiet. Jednak wyrazy w tym przykładzie są zbyt liczone z powodu łącznika.
stringi::stri_count_words(txt) #11 words
źródło
Ze stringr pakietu można również napisać prosty skrypt, który mógłby przejść przez wektor łańcuchów, na przykład przez pętlę for.
Powiedzmy
zawiera wektor ciągów, które chcemy przeanalizować. Najpierw dodajemy dodatkowe kolumny do istniejącej ramki danych df, jak poniżej:
df$strings = as.integer(NA) df$characters = as.integer(NA)
Następnie uruchamiamy pętlę for na wektorze ciągów, jak poniżej:
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 }
Wynikowe kolumny: łańcuchy i znak będą zawierały liczbę słów i znaków, a zostanie to osiągnięte za jednym razem dla wektora ciągów.
źródło