Счетчик совпадений в 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 ответов

Решение

Два быстрых совета:

  1. избегайте двойного цикла for, он вам не нужен;)
  2. использовать 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
Другие вопросы по тегам