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.
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.
Odpowiedzi:
Możesz używać strsplit
i sapply
funkcji
sapply(strsplit(str1, " "), length)
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łów
sapply(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żywanie strsplit()
(jak @ user813966, ale z wyrażeniem regularnym do oddzielania słów) i używanie oryginalnego pojęcia rozdzielania słów
lengths(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ń.
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1
zwroty 4
i 8
. Pierwsza poprawna, druga za dużo. Myślę, że liczy się interpunkcja.
sapply(gregexpr("\\W+", "word"), length) + 1
zwraca 2
Najprostszy 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
Używam str_count
funkcji z stringr
biblioteki z sekwencją ucieczki, \w
która reprezentuje:
dowolny znak `` słowa '' (litera, cyfra lub podkreślenie w bieżącym języku: w trybie UTF-8 uwzględniane są tylko litery i cyfry ASCII)
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
'[\\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
i friggin'
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
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]])
Wypróbuj tę funkcję z stringi
pakietu
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
Możesz usunąć podwójne spacje i policzyć liczbę " "
w ciągu, aby uzyskać liczbę słów. Użyj stringr i rm_white
{ qdapRegex }
str_count(rm_white(s), " ") +1
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
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
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
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
df $ tekst
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.