Счетчик совпадений в R
Как эффективно подсчитать количество экземпляров одной символьной строки, которые встречаются в другой символьной строке?
Ниже мой код на сегодняшний день. Он успешно идентифицирует, встречается ли какой-либо экземпляр одной строки в другой строке. Однако я не знаю, как расширить его от отношения ИСТИНА / ЛОЖЬ до отношения подсчета.
x <- ("Hello my name is Christopher. Some people call me Chris")
y <- ("Chris is an interesting person to be around")
z <- ("Because he plays sports and likes statistics")
lll <- tolower(list(x,y,z))
dict <- tolower(c("Chris", "Hell"))
mmm <- matrix(nrow=length(lll), ncol=length(dict), NA)
for (i in 1:length(lll)) {
for (j in 1:length(dict)) {
mmm[i,j] <- sum(grepl(dict[j],lll[i]))
}
}
mmm
Это дает:
[,1] [,2]
[1,] 1 1
[2,] 1 0
[3,] 0 0
Поскольку строчная строка "chris" появляется дважды в lll[1]
мне бы хотелось mmm[1,1]
быть 2 вместо 1.
Реальный пример - гораздо более высокое измерение... так что хотелось бы, чтобы код можно было векторизовать вместо использования моей грубой силы для циклов.
5 ответов
Два быстрых совета:
- избегайте двойного цикла for, он вам не нужен;)
- использовать
stringr
пакет
library(stringr)
dict <- setNames(nm=dict) # simply for neatness
lapply(dict, str_count, string=lll)
# $chris
# [1] 2 1 0
#
# $hell
# [1] 1 0 0
Или как матрица:
# sapply(dict, str_count, string=lll)
# chris hell
# [1,] 2 1
# [2,] 1 0
# [3,] 0 0
Вы также можете сделать что-то вроде этого:
count.matches <- function(pat, vec) sapply(regmatches(vec, gregexpr(pat, vec)), length)
mapply(count.matches, c('chris', 'hell'), list(lll))
# chris hell
# [1,] 2 1
# [2,] 1 0
# [3,] 0 0
Вместо sum(grepl(dict[j],lll[i]))
, пытаться sum(gregexpr(dict[j],lll[i])[[1]] > 0)
llll<-rep(lll,length(dict))
dict1<-rep(dict,each=length(lll))
do.call(rbind,Map(function(x,y)list(y,sum(gregexpr(y,x)[[1]] > 0)), llll,dict1))
[,1] [,2]
hello my name is christopher. some people call me chris "chris" 2
chris is an interesting person to be around "chris" 1
because he plays sports and likes statistics "chris" 0
hello my name is christopher. some people call me chris "hell" 1
chris is an interesting person to be around "hell" 0
because he plays sports and likes statistics "hell" 0
Вы можете использовать reshape
чтобы получить то, что вы хотите.
Это использует пакет qdap. Версия CRAN должна работать нормально, но вы можете захотеть версию dev
library(qdap)
termco(c(x, y, z), 1:3, c('chris', 'hell'))
## 3 word.count chris hell
## 1 1 10 2(20.00%) 1(10.00%)
## 2 2 8 1(12.50%) 0
## 3 3 7 0 0
termco(c(x, y, z), 1:3, c('chris', 'hell'))$raw
## 3 word.count chris hell
## 1 1 10 2 1
## 2 2 8 1 0
## 3 3 7 0 0