【问题标题】:R frequency count by matching stringsR通过匹配字符串进行频率计数
【发布时间】:2014-07-08 18:03:22
【问题描述】:

请问有人可以帮我解答这个问题吗?非常感谢!

我有一些这样的数据:

    A             B
fruit     red apple
fruit   green apple
fruit  yellow apple
fruit          kiwi
fruit   golden kiwi
juice   apple juice
juice  orange juice

我想得到以下信息:

    A             B         freq
fruit         apple            3
fruit          kiwi            2
juice         apple            1
juice        orange            1

我可以提供要在 B 中搜索的字符串向量(即我知道我想查找“apple”、“kiwi”和“orange”)。例如,如果“fruit”中有“banana”,而我要搜索的项目列表中没有“banana”,则只需在结果中显示“banana”,频率为 1。

【问题讨论】:

  • 尝试sum(grepl('apple',data[,2])) 获取带有 "apple" 的行数。
  • @CarlWitthoft,谢谢!但我真正想要的是A中每个类别中“苹果”的频率,即“水果”和“果汁”中“苹果”的频率。
  • 好吧,然后想想 :-) sum(grepl('apple',data[data[,1]=="fruit",2])) 等等。
  • 你是对的,这确实有效!但问题是,我的数据集非常大,A 中的类别(数千个)比给定的两个多得多。有没有更自动化的方法?

标签: r


【解决方案1】:

计算具有特定值的观察次数是与table 的单行:

library(stringr)
table(paste(df$A, str_extract(df$B, paste(lookingfor, collapse="|")), sep="."))
#  fruit.apple   fruit.kiwi  juice.apple juice.orange 
#            3            2            1            1 

在这里,paste(lookingfor, collapse="|") 生成一个正则表达式来查找您的所有单词,str_extract 提取您要查找的单词,外部 pasteA 变量与提取的值组合在一起(用 @ 分隔987654327@) 和 table 计算每个配对的计数。

【讨论】:

  • 谢谢!我尝试了你的建议,效果很好!最后一件事:我怎样才能修改你的代码,这样我就不会得到像fruit.NA 这样的输出?当B 包含lookingfor 之外的项目时,会发生这种情况。在这种情况下,我希望有有意义的输出(例如fruit.banana)。
  • @scat5218 很容易过滤掉B中没有匹配的任何观察;你会想要像e <- str_extract(df$B, paste(lookingfor, collapse="|"))table(paste(df$A[!is.na(e)], e[!is.na(e)], sep=".")) 这样的东西。如果要从 B 列中提取“香蕉”,则必须将其添加到 lookingfor
【解决方案2】:

假设您的数据框名为df

library(dplyr)

df %>%
  mutate(categ = sapply(regmatches(B, regexec("apple|kiwi|orange",B)),'[',1)) %>%
  group_by(A,categ) %>%
  mutate(freq = n()) %>%
  select(A,B=categ,freq) %>%
  summarize(freq = first(freq))

返回

      A      B freq
1 fruit  apple    3
2 fruit   kiwi    2
3 juice  apple    1
4 juice orange    1

【讨论】:

  • 谢谢乔治!你知道为什么这个给我Error in regexec("apple|kiwi|orange", c(6L, 3L, 7L, 4L, 2L, 1L, 5L)) : invalid 'text' argument吗?
  • 如果您尝试使用 ?regexec,您将看到第二个参数必须是字符向量(寻找匹配的地方)。我已将数据框第二列的名称传递给 text 参数。
  • 我明白了!最后一个问题:有没有办法在我的搜索列表中未包含的B 的结果项中显示?我的实际B 列中有许多类型的项目。我指定要搜索的项目是主要项目,但我确实想知道其他项目是什么。谢谢!
【解决方案3】:

这样的事情可能对你有用。它依赖于您提供的字符串向量与原始数据中的单词完全匹配这一事实。

# your data
df <- data.frame(A = rep(c("fruit", "juice"), c(5, 2)),
    B = c("red apple", "green apple", "yellow apple", "kiwi", "golden kiwi", "apple juice", "orange juice"))

# vector of strings to search for
lookingfor <- c("apple", "kiwi", "orange", "banana")

# function to split up words in df$B and find those that match to those in looking for
found <- function(longname, shortnames) {
    splitlong <- strsplit(longname, " ")[[1]]
    index <- match(splitlong, shortnames)
    res <- if(all(is.na(index))) NA else shortnames[index[!is.na(index)][1]]
    res
    }

# apply the function to your data
df$C <- sapply(df$B, found, shortnames=lookingfor)

# summarize
aggregate(data.frame(freq=!is.na(df$C)), list(A=df$A, B=df$C), sum)

【讨论】:

  • 谢谢!我在 R 中尝试过,但它抱怨 Error in strsplit(longname, " ") : non-character argument
【解决方案4】:

这是一种方法。首先找出第一列有多少个“类别”。

categs <- unique(data[,1])
fruits <- c('apple','orange', 'kiwi') # or whatever
results<-matrix(ncol=3)

然后对于categs 中的每个值,搜索每种已知水果。

for (j in 1:length(categs) ) {
    for (k in 1:length(fruits) ) {
        results[1 + j*(k-1),1]<-categs[j]
        results[1 + j*(k-1),2]<-fruits[j]
        results[1 + j*(k-1),1]<-sum(grepl(fruits[k],data[data[,1]==fruits[k],2]))
        }
    }

我没有测试过,所以毫无疑问我有一些索引错误。

【讨论】:

    【解决方案5】:

    通过获取您拥有的数据集并将其声明为dat,您可以执行以下操作:

    library(dplyr)
    
    dat %>%
    
      mutate(B = sub(' juice', '', B),
             B = ifelse(grepl(' apple', B), 'apple', B),
             B = ifelse(grepl('golden ', B), sub('golden ', '', B), B)) %>%
    
    group_by(A, B) %>%
    summarise(count = n())
    

    必须将其他规则添加到 mutate 语句中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-10
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-13
      相关资源
      最近更新 更多