【问题标题】:R: Count unique values by categoryR:按类别计算唯一值
【发布时间】:2013-04-23 01:10:22
【问题描述】:

我在 R 中有如下数据:

 Cnty   Yr   Plt       Spp  DBH Ht Age
 1  185 1999 20001 Bitternut  8.0 54  47
 2  185 1999 20001 Bitternut  7.2 55  50
 3   31 1999 20001    Pignut  7.4 71  60
 4   31 1999 20001    Pignut 11.4 85 114
 5  189 1999 20001        WO 14.5 80  82
 6  189 1999 20001        WO 12.1 72  79

我想知道每个县 (Cnty) 中独特物种 (Spp) 的数量。 "unique(dfname$Spp)" 为我提供了数据框中独特物种的总数,但我希望按县显示。

感谢任何帮助!抱歉,奇怪的格式,这是我关于 SO 的第一个问题。

谢谢。

【问题讨论】:

  • 欢迎来到 SO。分享更多关于您尝试过什么以及您遇到问题的地方将产生更好的答案。但是,为了帮助您入门,aggregatetapply 之类的函数会很有帮助。记得查看使用?aggregate的函数的帮助文本。

标签: r count unique categories


【解决方案1】:

我已尝试让您的示例数据更有趣。您的样本数据目前每个“Cnty”只有一个唯一的“Spp”。

set.seed(1)
mydf <- data.frame(
  Cnty = rep(c("185", "31", "189"), times = c(5, 3, 2)),
  Yr = c(rep(c("1999", "2000"), times = c(3, 2)), 
         "1999", "1999", "2000", "2000", "2000"),
  Plt = "20001",
  Spp = sample(c("Bitternut", "Pignut", "WO"), 10, replace = TRUE),
  DBH = runif(10, 0, 15)
)
mydf
#    Cnty   Yr   Plt       Spp       DBH
# 1   185 1999 20001 Bitternut  3.089619
# 2   185 1999 20001    Pignut  2.648351
# 3   185 1999 20001    Pignut 10.305343
# 4   185 2000 20001        WO  5.761556
# 5   185 2000 20001 Bitternut 11.547621
# 6    31 1999 20001        WO  7.465489
# 7    31 1999 20001        WO 10.764278
# 8    31 2000 20001    Pignut 14.878591
# 9   189 2000 20001    Pignut  5.700528
# 10  189 2000 20001 Bitternut 11.661678

接下来,正如建议的那样,tapply 是一个不错的候选者。结合uniquelength 来获取您要查找的数据。

with(mydf, tapply(Spp, Cnty, FUN = function(x) length(unique(x))))
# 185 189  31 
#   3   2   2 
with(mydf, tapply(Spp, list(Cnty, Yr), FUN = function(x) length(unique(x))))
#     1999 2000
# 185    2    2
# 189   NA    2
# 31     1    1

如果您对简单的制表感兴趣(不是唯一值),那么您可以探索tableftable

with(mydf, table(Spp, Cnty))
#            Cnty
# Spp         185 189 31
#   Bitternut   2   1  0
#   Pignut      2   1  1
#   WO          1   0  2
ftable(mydf, row.vars="Spp", col.vars=c("Cnty", "Yr"))
#           Cnty  185       189        31     
#           Yr   1999 2000 1999 2000 1999 2000
# Spp                                         
# Bitternut         1    1    0    1    0    0
# Pignut            2    0    0    1    0    1
# WO                0    1    0    0    2    0

【讨论】:

  • 阿南达:很好的答案!您正确地假设每个县存在不止一种物种,这正是我需要计算的。非常感谢您的帮助。
  • @KlausLouis,很高兴听到这个消息。如果这个或任何其他答案有帮助,请考虑支持它们和/或accepting 其中一个。谢谢,欢迎来到 Stack Overflow! :)
【解决方案2】:

正如贾斯汀所说,聚合可能是你想要的。如果您将数据框称为 foo,那么以下内容应该可以满足您的需求,即每个物种的个体数量,假设每行 Butternut 代表一个属于该物种的唯一个体。注意我使用 foo$Age 来计算向量的长度,即属于每个物种的个体(行)的数量,但你可以使用 foo$Ht 或 foo$DBH 等。

aggregate(foo$Age, by = foo[c('Spp','Cnty')], length)

干杯,

丹尼

【讨论】:

    【解决方案3】:
    set.seed(1)
    mydf <- data.frame(
      Cnty = rep(c("185", "31", "189"), times = c(5, 3, 2)),
      Yr = c(rep(c("1999", "2000"), times = c(3, 2)), 
             "1999", "1999", "2000", "2000", "2000"),
      Plt = "20001",
      Spp = sample(c("Bitternut", "Pignut", "WO"), 10, replace = TRUE),
      DBH = runif(10, 0, 15)
    )
    mydf
    

    dplyr 包可以在这里提供帮助:

    
    library(dplyr)
    mydf %>% 
      group_by(Cnty) %>% 
      summarise(un_Spp = length(unique(Spp)))
    #> # A tibble: 3 × 2
    #>   Cnty  un_Spp
    #>   <chr>  <int>
    #> 1 185        3
    #> 2 189        2
    #> 3 31         2
    

    【讨论】:

      【解决方案4】:
      with(mydf, tapply(Spp, list(Cnty, Yr), 
           FUN = function(x) length(unique(x))))
      

      唯一查询不适用于大型数据集,我的意思是超过 1000k 行的数据。

      【讨论】:

        【解决方案5】:

        我想补充一下 A Handcart And Mohair 提到的内容。对于那些想要将下面代码的结果放入数据框的人(在 R 工作室中很有帮助)...

        with(mydf, table(Spp, Cnty))
        #            Cnty
        # Spp         185 189 31
        #   Bitternut   2   1  0
        #   Pignut      2   1  1
        #   WO          1   0  2
        ftable(mydf, row.vars="Spp", col.vars=c("Cnty", "Yr"))
        #           Cnty  185       189        31     
        #           Yr   1999 2000 1999 2000 1999 2000
        # Spp                                         
        # Bitternut         1    1    0    1    0    0
        # Pignut            2    0    0    1    0    1
        # WO                0    1    0    0    2    0
        

        您需要将 as.data.frame.matrix 修饰符放在代码前面,如下所示:

        as.data.frame.matrix(with(mydf, table(Spp, Cnty)))
        

        当我看到这篇文章时,我对 R 还很陌生,我花了很长时间才弄明白,所以我想我会分享。

        【讨论】:

          【解决方案6】:

          使用data.table 方法的简单解决方案。

          library(data.table)
          
          output <- setDT(mydf)[ , .(count=.N) , by = .(Spp,Cnty)]
          

          如果您想将输出重塑为更好的表格格式:

          library(tidyr)
          
          spread(data=a, key =Spp, count)
          
          #   Cnty Bitternut Pignut WO
          # 1:  185         2      2  1
          # 2:  189         1      1 NA
          # 3:   31        NA      1  2
          
          # or perhaps like this:
          
          spread(data=a, key =Cnty, count)
          
          #          Spp 185 189 31
          # 1: Bitternut   2   1 NA
          # 2:    Pignut   2   1  1
          # 3:        WO   1  NA  2
          

          【讨论】:

            【解决方案7】:

            我们现在可以使用计数功能来简化此操作。

            tally(group_by(mydf, Spp, Cnty))
            
                    Spp   Cnty     n
                 <fctr> <fctr> <int>
            1 Bitternut    185     2
            2 Bitternut    189     1
            3    Pignut    185     2
            4    Pignut    189     1
            5    Pignut     31     1
            6        WO    185     1
            7        WO     31     2
            

            【讨论】:

            • 计算出现次数,而不是唯一值
            猜你喜欢
            • 2015-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多