[regex] 문자열 열의 각 행에서 주어진 문자의 발생 횟수를 계산하는 방법은 무엇입니까?

특정 변수에 텍스트 문자열이 포함 된 data.frame이 있습니다. 각 개별 문자열에서 주어진 문자의 발생 횟수를 계산하고 싶습니다.

예:

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

문자열에서 “a”의 발생 횟수 (예 : c (2,1,0))를 사용하여 q.data에 대한 새 열을 만들고 싶습니다.

내가 관리 한 유일한 복잡한 접근 방식은 다음과 같습니다.

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



답변

stringr 패키지는 str_count관심있는 작업을 수행하는 것처럼 보이는 기능을 제공합니다 .

# 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


답변

기본 R을 떠나고 싶지 않다면 여기에 상당히 간결하고 표현 가능한 가능성이 있습니다.

x <- q.data$string
lengths(regmatches(x, gregexpr("a", x)))
# [1] 2 1 0


답변

nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))
[1] 2 1 0

nchar에 전달하기 전에 factor 변수를 문자로 강제 변환합니다. 정규식 함수는 내부적으로이를 수행하는 것으로 보입니다.

다음은 벤치 마크 결과입니다 (테스트 크기를 3000 행으로 확장).

 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


답변

sum(charToRaw("abc.d.aa") == charToRaw('.'))

좋은 선택입니다.


답변

stringi패키지는 기능을 제공 stri_count하고 stri_count_fixed있는 매우 빠르다.

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

기준

@ 42-의 대답 의 가장 빠른 접근 방식 과 30.000 요소가있는 벡터에 대한 stringr패키지동등한 기능 과 비교됩니다 .

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)

데이터

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

여기에 이미지 설명 입력


답변

https://stackoverflow.com/a/12430764/589165 의 변형 은 다음과 같습니다.

> nchar(gsub("[^a]", "", q.data$string))
[1] 2 1 0


답변

나는 누군가가 더 잘할 수 있다고 확신하지만 이것은 작동합니다.

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

또는 함수에서 :

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