【问题标题】:Can R automatically recognize and count the number of occurrences of a word in n number of columns?R能自动识别并统计一个单词在n列中出现的次数吗?
【发布时间】:2015-07-06 03:23:21
【问题描述】:

这是一个沉重的问题,但我会尽力解释。我正在尝试编写一个程序来跟踪昆虫随时间访问某种花卉的次数。为此,我有一个如下所示的数据集:

ID          Visit_Freq   Visitor_1   Visitor_2   Visitor_3   Visitor_4   Visitor_5
1             1.0000000  Halictidae       <NA>       <NA>       <NA>       <NA>
2             5.0000000  Syrphidae Halictidae  Syrphidae  Syrphidae       Apis
3             1.0000000        Apis       <NA>       <NA>       <NA>       <NA>
4             0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>
5             0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>
6             0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>
7             0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>
8             2.0000000        Apis       Apis       <NA>       <NA>       <NA>
9             0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>
10            0.0000000        <NA>       <NA>       <NA>       <NA>       <NA>

在“Visitor_n”列下,我记录了访问过那朵花的昆虫类型,或者没有访问过的 NA。为了分析我们的数据,我们必须在整个访客列中计算每种昆虫类型的出现次数。有时,一朵花 (ID) 可以有多达 10 个访客,而我们的 ID 计数通常超过 500,因此手动计算出现次数可能是一件苦差事。以下是我为使其更容易所做的工作:

Apis <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Apis'))))

到目前为止,上面的那一行已经很好地计算了 Apis 在我的真实数据集中出现的次数,但问题是实际上有几十种昆虫类型可能会或可能不会访问我们的植物,所以为了安全起见,我必须有大约 30-50 行类似的代码,每行都将“Apis”替换为不同的昆虫类型......例如......

Apis <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Apis'))))
Bombus <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Bombus'))))
Halictidae <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Halictidae'))))
Syrphidae <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Syrphidae'))))
Skipper <- sum(apply(DataSet[3:7], 2, function(x) length(which(x == 'Skipper'))))

等等等等

如果我能找到一种方法让 R 自动识别“昆虫 A、B、D、F 和 H 出现在 [3:7] 列中,这将是非常有帮助的,这里是它们出现的次数都发生了”,例如,而不必为每只昆虫打出 30-50 行来确保我没有遗漏任何东西。

我不反对为此安装软件包,但如果可能的话,我希望它尽可能接近基础 R。我想把这个介绍给我的一些几乎没有 R 经验的实验室伙伴。

我昨晚确实问了一个类似的问题,但从那以后我取得了一些进展。

【问题讨论】:

  • table(unlist(DataSet[, grep('Visitor', names(DataSet))]))?
  • 您遇到的根本问题是您的数据不整齐。您实际上应该只有 4 列,ID、Visit_Freq、Visitor_Number、Species。然后,在这种格式下,您想要做的很容易在 dplyr 中使用诸如summarizetally 之类的函数。如果您可以发布生成您正在处理的类型的数据框的代码,那么我很乐意展示如何将其重新排列成整洁的形式,然后进行总结。
  • @ClausWilke 这怎么不“整洁”?这就是我们在业界通常所说的“宽”格式。有“宽”格式和“长”格式。您似乎在暗示“长”格式是“整洁的”,因此是“正确的”。也许如果一个人的技能只在哈德利宇宙中,那么使用长格式会更好,但我们不要建议人们以这种方式限制自己,好吗?
  • @rawr 在这里,“整洁”是一个技术术语,正如 Wickham 的论文中所定义的那样。这与格式是否正确无关。显然,长表和宽表都包含相同的信息,因此同样正确。然而,在许多情况下,长表的分析要简单得多,这仅仅是因为我们有更好的工具来处理长表而不是宽表。此外,在这种特殊情况下,访问者的数量是先验未知的,因此宽表似乎是一个特别糟糕的选择,这会导致大量的 NA。
  • @ClausWilke——我当然不介意。我目前在茫茫荒野中,很多时候几乎没有互联网访问权限,所以我可能有点难以回复每个人。感谢大家的回答,他们都很有见地。

标签: r


【解决方案1】:

此解决方案假定您的昆虫名称只有英文字母,没有数字,第一个字母大写,其余字母小写。

data.frame(table(grep("[A-Z]{1}[a-z]+",stack(df1)[,1],value=TRUE)))
        Var1 Freq
1       Apis    4
2 Halictidae    2
3  Syrphidae    3

数据

df1<-
structure(list(ID = 1:10, Visit_Freq = c(1, 5, 1, 0, 0, 0, 0, 
2, 0, 0), Visitor_1 = c("Halictidae", "Syrphidae", "Apis", "<NA>", 
"<NA>", "<NA>", "<NA>", "Apis", "<NA>", "<NA>"), Visitor_2 = c("<NA>", 
"Halictidae", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "Apis", 
"<NA>", "<NA>"), Visitor_3 = c("<NA>", "Syrphidae", "<NA>", "<NA>", 
"<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>"), Visitor_4 = c("<NA>", 
"Syrphidae", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>", 
"<NA>", "<NA>"), Visitor_5 = c("<NA>", "Apis", "<NA>", "<NA>", 
"<NA>", "<NA>", "<NA>", "<NA>", "<NA>", "<NA>")), .Names = c("ID", 
"Visit_Freq", "Visitor_1", "Visitor_2", "Visitor_3", "Visitor_4", 
"Visitor_5"), row.names = c(NA, -10L), class = "data.frame")

【讨论】:

    【解决方案2】:

    只需用我们的昆虫名称创建一个向量

    insects <- c( "Apis", "Halictidae", "Syrphidae" )
    

    你也可以通过

    自动获取
    insects <- unique( unlist( DataSet[ 3:7 ] ) )
    insects <- insects[ -( which ( insects == "<NA>" ) ) ]
    

    然后创建一个获取访问次数的空变量

    count <- NULL
    

    那么你就可以保留你所拥有的,然后循环浏览昆虫的名字

    for( i in insects ) 
        count <- c( count, sum( apply( DataSet[ 3:7 ], 2, 
                           function( x ) length( which( x == i) ) ) ) )
    count
    [1] 4 2 3
    

    如果你愿意,你可以将两者结合起来

    insectCount <- data.frame( insects, count )
    insectCount
         insects count
    1       Apis     4
    2 Halictidae     2
    3  Syrphidae     3
    

    请注意,根据您是手动创建还是自动创建矢量,昆虫的顺序会有所不同。无论哪种情况,计数都相同。

    【讨论】:

      【解决方案3】:

      对于这类问题,我喜欢dplyr,因为只要数据格式正确(整洁),问题就可以在一行中得到解决。要将数据转换成整洁的格式,我们需要多一行(使用 tidyr 包中的 gather())。

      我正在使用 user227710 定义的数据框 here. 请注意,它包含字符串“”而不是正确的 R NA,因此过滤掉 NA 的行看起来有点奇怪。

      实际工作由函数group_by()tally() 完成。你告诉 R 数据应该如何分组(这里是 Species 变量),然后 tally() 对它们进行计数。

      我理解,您不想使用外部包,但是对于任何定期处理数据的人来说,学习如何使用 tidyrdplyr 绝对值得。

      require(tidyr) # for gather()
      require(dplyr) # for group_by() and tally()
      
      # convert table into tidy (long) format
      df_long <- gather(df1, Visitor, Species, Visitor_1:Visitor_5)
      head(df_long)
      ##   ID Visit_Freq   Visitor    Species
      ## 1  1          1 Visitor_1 Halictidae
      ## 2  2          5 Visitor_1  Syrphidae
      ## 3  3          1 Visitor_1       Apis
      ## 4  4          0 Visitor_1       <NA>
      ## 5  5          0 Visitor_1       <NA>
      ## 6  6          0 Visitor_1       <NA>
      
      # now count species, excluding the <NA> value
      group_by(df_long, Species) %>%
          filter(Species != "<NA>") %>% 
          tally()
      ## Source: local data frame [3 x 2]
      ## 
      ##      Species  n
      ## 2       Apis  4
      ## 3 Halictidae  2
      ## 4  Syrphidae  3
      

      【讨论】:

        猜你喜欢
        • 2016-08-21
        • 2021-11-17
        • 1970-01-01
        • 2016-01-09
        • 2014-07-12
        • 2013-12-25
        • 2015-03-15
        • 1970-01-01
        相关资源
        最近更新 更多