所以我对 R 还很陌生,并且多年来一直在处理一个非常大的树木生长/死亡率数据集。由于死亡率并不总是正确记录,我需要搜索每一行的测量值(可以是胸高直径 (DBH) 或地高直径 (DGH)),然后,如果它们在最近一次调查之前停止,则有 R记录他们停止的年份,以便我可以计算出每年发生的推定死亡人数。我称之为死亡率
的数据框的结构如下:
year plant.id dbh dgh
1 1 3.2 na
2 1 3.3 na
3 1 3.5 na
4 1 3.6 na
1 2 na 1.0
2 2 na 1.1
3 2 na na
4 2 na na
我希望能够添加一列或类似的内容,然后给出给定植物“死亡”的年份,这样就可以很容易地计算数据集中该年的所有实例。像这样的事情会很棒:
year plant.id dbh dgh mort.year
1 1 3.2 na na
2 1 3.3 na na
3 1 3.5 na na
4 1 3.6 na na
1 2 na 1.0 na
2 2 na 1.1 na
3 2 na na 3
4 2 na na 3
1 3 2.2 na na
2 3 2.3 na na
3 3 2.4 na na
4 3 na na 4
由于以下原因,情况变得更加复杂:1)新植物生长并在以后的几年中添加,2)偶尔会错误地认为一棵树已死亡或丢失,因此当年没有进行测量,然后在随后的几年中,树实际上被发现是活的。结果数据如下所示:
year plant.id dbh dgh
1 4 na na
2 4 na 1.0
3 4 na 1.0
4 4 na 1.1
1 5 2.1 na
2 5 na na
3 5 2.2 na
4 5 2.2 na
出于死亡率估计的目的,我基本上想忽略这些(除非他们后来死亡),所以理想的结果是这样的:
year plant.id dbh dgh mort.year
1 4 na na na
2 4 na 1.0 na
3 4 na 1.0 na
4 4 na 1.1 na
1 5 2.1 na na
2 5 na na na
3 5 2.2 na na
4 5 2.2 na na
我大致知道如何让 R 计算给定年份的所有实例以获得最终结果,我的主要挑战是弄清楚我可以使用哪些命令/逻辑来让它进行搜索,然后生成一列像这样,所以任何有关如何做到这一点的提示/建议将不胜感激!
最佳答案
这是一种使用 data.table
的方法,希望它会很快:
library(data.table)
setDT(mortality)
setkey(mortality,plant.id,year)
mortality[, .(mort.year =
year[dbh == "na" &
dgh == "na" &
cumsum((dbh != "na" | dgh != "na")) == max(cumsum((dbh != "na" | dgh != "na")))]),
by = plant.id][,.(mort.year = min(mort.year)), by = plant.id]
plant.id mort.year
1: 2 3
2: 3 4
这适用于 3 个简单的逻辑比较。
dbh == "na"
(注意,如果值为NA
而不是,请将其替换为
)is.na
”呐”dgh == "na"
- 观测到测量的年数必须等于曾经进行过测量的最大年数。
可视化它可能会更容易理解:
mortality[, temp := cumsum((dbh != "na" | dgh != "na")), by = plant.id][]
year plant.id dbh dgh temp
1: 1 1 3.2 na 1
2: 2 1 3.3 na 2
3: 3 1 3.5 na 3
4: 4 1 3.6 na 4
5: 1 2 na 1.0 1
6: 2 2 na 1.1 2
7: 3 2 na na 2
8: 4 2 na na 2
9: 1 3 2.2 na 1
10: 2 3 2.3 na 2
11: 3 3 2.4 na 3
12: 4 3 na na 3
13: 1 4 na na 0
14: 2 4 na 1.0 1
15: 3 4 na 1.0 2
16: 4 4 na 1.1 3
17: 1 5 2.1 na 1
18: 2 5 na na 1
19: 3 5 2.2 na 2
20: 4 5 2.2 na 3
由于 NA
和双 min
返回之间的类型不一致,min
调用必须分开。 setkey
调用可确保年份排序正确。
如果需要,可以通过简单的连接来创建列:
result <- mortality[, .(mort.year = year[dbh == "na" & dgh == "na" & cumsum((dbh != "na" | dgh != "na")) == max(cumsum((dbh != "na" | dgh != "na")))]), by = plant.id][,.(mort.year = min(mort.year)), by = plant.id]
result[mortality,][, mort.year := fifelse(dbh == "na" & dgh == "na", mort.year, NA_integer_)][]
plant.id mort.year year dbh dgh
1: 1 NA 1 3.2 na
2: 1 NA 2 3.3 na
3: 1 NA 3 3.5 na
4: 1 NA 4 3.6 na
5: 2 NA 1 na 1.0
6: 2 NA 2 na 1.1
7: 2 3 3 na na
8: 2 3 4 na na
9: 3 NA 1 2.2 na
10: 3 NA 2 2.3 na
11: 3 NA 3 2.4 na
12: 3 4 4 na na
13: 4 NA 1 na na
14: 4 NA 2 na 1.0
15: 4 NA 3 na 1.0
16: 4 NA 4 na 1.1
17: 5 NA 1 2.1 na
18: 5 NA 2 na na
19: 5 NA 3 2.2 na
20: 5 NA 4 2.2 na
关于r - 如何让 R 逐行搜索大型数据集以查找两列之一中是否存在值,然后在数据丢失时返回一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62353298/