我有一个data.frame,其中某些变量包含文本字符串。我希望计算每个字符串中给定字符的出现次数。
示例:
q.data<-data.frame(number=1:3, string=c("greatgreat", "magic", "not"))
我希望为q.data创建一个新列,其中包含字符串中“a”的出现次数(即c(2,1,0))。
我管理的唯一令人费解的方法是:
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
答案 0 :(得分:110)
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
答案 1 :(得分:52)
如果你不想留下基地R,这里有一个相当简洁和富有表现力的可能性:
x <- q.data$string
lengths(regmatches(x, gregexpr("a", x)))
# [1] 2 1 0
答案 2 :(得分:14)
nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))
[1] 2 1 0
请注意,在传递给nchar之前,我将factor变量强制转换为character。正则表达式函数似乎在内部执行此操作。
这是基准测试结果(测试尺寸按比例增加到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
答案 3 :(得分:7)
sum(charToRaw("abc.d.aa") == charToRaw('.'))
是个不错的选择。
答案 4 :(得分:2)
我确信有人可以做得更好,但这样做有效:
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")
答案 5 :(得分:1)
您可以只使用字符串除法
require(roperators)
my_strings <- c('apple', banana', 'pear', 'melon')
my_strings %s/% 'a'
这将为您提供1、3、1、0。您还可以对正则表达式和整个单词使用字符串除法。
答案 6 :(得分:1)
stri_count
软件包提供了非常快速的功能stri_count_fixed
和stringi::stri_count(q.data$string, fixed = "a")
# [1] 2 1 0
。
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)
基准
与具有30.000个元素的向量相比,从@42-'s answer到equivalent function from the stringr
package最快的方法。
q.data <- data.frame(number=1:3, string=c("greatgreat", "magic", "not"), stringsAsFactors = FALSE)
test.data <- q.data[rep(1:NROW(q.data), 10000),]
数据
{{1}}
答案 7 :(得分:1)
https://stackoverflow.com/a/12430764/589165的变体是
> nchar(gsub("[^a]", "", q.data$string))
[1] 2 1 0
答案 8 :(得分:0)
恕我直言最简单,最干净的方式是:
.blue {
color: blue;
text-decoration : underline;
}
答案 9 :(得分:0)
以下问题已移至此处,但该页面似乎无法直接回答法拉赫·埃尔(Farah El)的问题。 How to find number 1s in 101 in R
以防万一,我在这里写下答案。
library(magrittr)
n %>% # n is a number you'd like to inspect
as.character() %>%
str_count(pattern = "1")
答案 10 :(得分:-1)
下一个表达式可以完成任务,并且不仅适用于字母,还适用于符号。
表达式的工作方式如下:
1:它在数据帧q.data的列上使用lapply来遍历列2的行(“ lapply(q.data [,2],”),
2:它对列2的每一行都应用一个函数“ function(x){sum('a'== strsplit(as.character(x),))[[1]])}”。 该函数获取第2列(x)的每个行值,转换为字符(例如,如果是一个因素),并且对每个字符进行字符串分割(“ strsplit(as.character(x),' ')“)。结果,我们有了一个向量,其中第2列的每一行都有字符串值的每个字符。
3:将向量的每个向量值与要计数的所需字符进行比较,在这种情况下为“ a”(“'a'==“)。此操作将返回一个True和False值“ c(True,False,True,....)”的向量,当向量中的值与要计数的所需字符匹配时为True。
4:计算字符“ a”在行中出现的总时间,作为向量“ sum(....)”中所有“ True”值的总和。
5:然后应用“ unlist”函数解压缩“ lapply”函数的结果并将其分配给数据框中的新列(“ q.data $ number.of.a <-unlist(。 ...“)
q.data$number.of.a<-unlist(lapply(q.data[,2],function(x){sum('a' == strsplit(as.character(x), '')[[1]])}))
>q.data
# number string number.of.a
#1 greatgreat 2
#2 magic 1
#3 not 0
答案 11 :(得分:-2)
s <- "aababacababaaathhhhhslsls jsjsjjsaa ghhaalll"
p <- "a"
s2 <- gsub(p,"",s)
numOcc <- nchar(s) - nchar(s2)
可能不是有效的,但解决了我的目的。