wake-up-neo.com

Wie berechnet man die Anzahl der Vorkommen eines bestimmten Zeichens in jeder Zeile einer Stringspalte?

Ich habe ein data.frame, in dem bestimmte Variablen eine Textzeichenfolge enthalten. Ich möchte die Anzahl der Vorkommen eines bestimmten Zeichens in jeder einzelnen Zeichenfolge zählen.

Beispiel:

q.data<-data.frame(number=1:3, string=c("greatgreat", "magic", "not"))

Ich möchte eine neue Spalte für q.data mit der Anzahl der Vorkommen von "a" in Zeichenfolge erstellen (z. B. c (2,1,0)).

Der einzige verschlungene Ansatz, den ich geschafft habe, ist:

string.counter<-function(strings, pattern){  
  counts<-NULL
  for(i in 1:length(strings)){
    counts[i]<-length(attr(gregexpr(pattern,strings[i])[[1]], "match.length")[attr(gregexpr(pattern,strings[i])[[1]], "match.length")>0])
  }
return(counts)
}

string.counter(strings=q.data$string, pattern="a")

 number     string number.of.a
1      1 greatgreat           2
2      2      magic           1
3      3        not           0
77

Das stringr-Paket enthält die str_count-Funktion, die scheinbar das tut, was Sie interessiert

# Load your example data
q.data<-data.frame(number=1:3, string=c("greatgreat", "magic", "not"), stringsAsFactors = F)
library(stringr)

# Count the number of 'a's in each element of string
q.data$number.of.a <- str_count(q.data$string, "a")
q.data
#  number     string number.of.a
#1      1 greatgreat           2
#2      2      magic           1
#3      3        not           0
102
Dason

Wenn Sie Basis R nicht verlassen möchten, haben Sie hier eine recht knappe und ausdrucksstarke Möglichkeit:

x <- q.data$string
lengths(regmatches(x, gregexpr("a", x)))
# [1] 2 1 0
49
Josh O'Brien
nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))
[1] 2 1 0

Beachten Sie, dass ich die Faktorvariable in Zeichen umwandeln muss, bevor Sie an nchar übergeben werden. Die Regex-Funktionen scheinen dies intern zu tun.

Hier die Benchmark-Ergebnisse (mit einer vergrößerten Größe des Tests auf 3000 Zeilen)

 q.data<-q.data[rep(1:NROW(q.data), 1000),]
 str(q.data)
'data.frame':   3000 obs. of  3 variables:
 $ number     : int  1 2 3 1 2 3 1 2 3 1 ...
 $ string     : Factor w/ 3 levels "greatgreat","magic",..: 1 2 3 1 2 3 1 2 3 1 ...
 $ number.of.a: int  2 1 0 2 1 0 2 1 0 2 ...

 benchmark( Dason = { q.data$number.of.a <- str_count(as.character(q.data$string), "a") },
 Tim = {resT <- sapply(as.character(q.data$string), function(x, letter = "a"){
                            sum(unlist(strsplit(x, split = "")) == letter) }) }, 

 DWin = {resW <- nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))},
 Josh = {x <- sapply(regmatches(q.data$string, gregexpr("g",q.data$string )), length)}, replications=100)
#-----------------------
   test replications elapsed  relative user.self sys.self user.child sys.child
1 Dason          100   4.173  9.959427     2.985    1.204          0         0
3  DWin          100   0.419  1.000000     0.417    0.003          0         0
4  Josh          100  18.635 44.474940    17.883    0.827          0         0
2   Tim          100   3.705  8.842482     3.646    0.072          0         0
11
42-
sum(charToRaw("abc.d.aa") == charToRaw('.'))

ist eine gute Option.

5
Zhang Tao

Ich bin sicher, dass es jemand besser machen kann, aber das funktioniert:

sapply(as.character(q.data$string), function(x, letter = "a"){
  sum(unlist(strsplit(x, split = "")) == letter)
})
greatgreat      magic        not 
     2          1          0 

oder in einer Funktion:

countLetter <- function(charvec, letter){
  sapply(charvec, function(x, letter){
    sum(unlist(strsplit(x, split = "")) == letter)
  }, letter = letter)
}
countLetter(as.character(q.data$string),"a")
2
tim riffe

Das Paket stringi bietet die Funktionen stri_count und stri_count_fixed, die sehr schnell sind.

stringi::stri_count(q.data$string, fixed = "a")
# [1] 2 1 0

benchmark

Verglichen mit der schnellsten Annäherung von @ 42-s Antwort und der äquivalente Funktion aus dem Paket stringr für einen Vektor mit 30.000 Elementen.

library(microbenchmark)

benchmark <- microbenchmark(
  stringi = stringi::stri_count(test.data$string, fixed = "a"),
  baseR = nchar(test.data$string) - nchar(gsub("a", "", test.data$string, fixed = TRUE)),
  stringr = str_count(test.data$string, "a")
)

autoplot(benchmark)

Daten

q.data <- data.frame(number=1:3, string=c("greatgreat", "magic", "not"), stringsAsFactors = FALSE)
test.data <- q.data[rep(1:NROW(q.data), 10000),]

enter image description here

1
markus

Der einfachste und sauberste Weg IMHO ist:

q.data$number.of.a <- lengths(gregexpr('a', q.data$string))

#  number     string number.of.a`
#1      1 greatgreat           2`
#2      2      magic           1`
#3      3        not           0`
0

Ich zähle Charaktere genauso wie Amarjeet. Ich bevorzuge es jedoch, es in einer einzigen Zeile zu machen.

HowManySpaces<-nchar(DF$string)-nchar(gsub(" ","",DF$string)) # count spaces in DF$string
0
cineS.

Die folgende Frage wurde hierher verschoben, aber es scheint, dass diese Seite Farah Els Frage nicht direkt beantwortet. Wie Nummer 1s in 101 in R zu finden

Also schreibe ich hier eine Antwort, nur für den Fall.

library(magrittr)
n %>% # n is a number you'd like to inspect
  as.character() %>%
  str_count(pattern = "1")

https://stackoverflow.com/users/8931457/farah-el

0
Yoshiaki

Eine Variation von https://stackoverflow.com/a/12430764/589165 ist

> nchar(gsub("[^a]", "", q.data$string))
[1] 2 1 0
0
s <- "aababacababaaathhhhhslsls jsjsjjsaa ghhaalll"
p <- "a"
s2 <- gsub(p,"",s)
numOcc <- nchar(s) - nchar(s2)

Kann nicht der effiziente sein, aber mein Ziel lösen.  

0
Amarjeet

Sie können nur die String-Division verwenden

require(roperators)
my_strings <- c('Apple', banana', 'pear', 'melon')
my_strings %s/% 'a'

Damit erhalten Sie 1, 3, 1, 0. Sie können die Zeichenfolgenaufteilung auch mit regulären Ausdrücken und ganzen Worten verwenden. 

0
Benbob