我在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的问题。
感谢。
答案 0 :(得分:16)
我试图让您的示例数据更有趣。您的样本数据目前每个“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
是一个很好的候选人。结合unique
和length
来获取您要查找的数据。
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
如果您对简单制表(不是唯一值)感兴趣,那么您可以浏览table
和ftable
:
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
答案 1 :(得分:2)
Justin提到聚合可能就是你想要的。如果你调用你的数据框foo,那么下面的代码应该给你你想要的东西,即每个物种的个体数量,假设每条有Butternut的行代表属于胡桃属的独特个体。注意我使用foo $ Age来计算向量的长度,即属于每个物种的个体(行)的数量,但你可以使用foo $ Ht或foo $ DBH等。
aggregate(foo$Age, by = foo[c('Spp','Cnty')], length)
干杯,
丹尼
答案 2 :(得分:0)
with(mydf, tapply(Spp, list(Cnty, Yr),
FUN = function(x) length(unique(x))))
唯一查询不适用于大数据集我的意思是数据超过1000k行。
答案 3 :(得分:0)
我想补充一下“手推车和马海毛”所提到的内容。对于那些想要将下面代码的结果导入数据框的人(在R studio中有用)......
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很新,我花了很长时间才弄明白,所以我想我会分享。
答案 4 :(得分:0)
使用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
答案 5 :(得分:0)
我们现在可以使用tally函数来简化这一过程。
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
答案 6 :(得分:0)
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::count()
函数看起来像一个简单的解决方案:
library(dplyr)
count(mydf, Spp, Cnty)
# A tibble: 7 x 3
# Spp Cnty n
# <fct> <fct> <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