R - 克服 "cut" 忽略数据范围外的值 table
R - overcome "cut" ignoring values outside of range in data table
我正在比较两年的每日土壤水分 (SM) 测量值。一年内,SM 介于 0 到 0.6 之间。
在下雨更多的另一年,SM 介于 0 到 0.8 之间。在这些数据中,我还有一些 NA's
,其中 SM 传感器由于某种原因无法工作。
让我们重新创建类似的东西:
library(data.table)
set.seed(24)
dt1 <- data.table(date=seq(as.Date("2015-01-01"), length.out=365, by="1 day"),
sm=sample(c(NA, runif(10, min=0, max=0.6)), 365, replace = TRUE))
dt2 <- data.table(date=seq(as.Date("2015-01-01"), length.out=365, by="1 day"),
sm=sample(c(NA, runif(10, min=0, max=0.8)), 365, replace = TRUE))
我正在尝试根据每个月 SM 类 之间的值比例来比较两个数据集。
我感兴趣的类是seq(0, 0.8, by=0.2)
。我还需要统计每个月测量失败的比例(NA
)。
我设法通过使用 akrun
的有用答案做到了这一点:
tmp1 <- dt1[, n := .N, month(date)][, .(perc=100 * .N/n[1]),
by=.(month=month(date),
grp=cut(sm, breaks=seq(0, 0.8, by=0.2),
labels = c('0-0.2', '0.2-0.4', '0.4-0.6', '0.6-0.8')))]
tmp2 <- dt2[, n := .N, month(date)][, .(perc=100 * .N/n[1]),
by=.(month=month(date),
grp=cut(sm, breaks=seq(0, 0.8, by=0.2),
labels = c('0-0.2', '0.2-0.4', '0.4-0.6', '0.6-0.8')))]
但是,输出并不完全符合我的预期。 由于 dt1
中的值仅介于 0 到 0.6 之间,因此结果数据中根本没有 0.6-0.8
类别 table tmp1
.
看起来 cut
忽略了最后一个类别 (0.6-0.8
),因为该范围内没有 SM 测量。这让我的比较真的很不方便,因为我在结果数据 tables tmp1
和 tmp2
.
中没有相同的组
有谁知道如何解决这个问题,即如何 "force" cut
考虑突破范围之外的值?我需要 tmp1
和 tmp2
中的所有 SM 类别,即使它们的计数为 0。
仅供参考,如果我们使用 table
,则不会发生此问题,它始终显示所有类别,即使它们的计数为零:
t1 <- runif(10, 0, 0.6)
t2 <- runif(10, 0, 0.8)
table(cut(t1, breaks=seq(0, 0.8, by=0.2)))
(0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8]
5 3 2 0
table(cut(t2, breaks=seq(0, 0.8, by=0.2)))
(0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8]
1 3 2 4
感谢任何意见。
使用CJ
计算所有级别,甚至那些没有出现在table中的级别:
f = function(d){
# create month column
d[, month := month(date)]
# roll to make cut-group column
mdt = data.table(sm = c(NA, seq(0, .8, by=.2)))
d[, lb := mdt[.SD, on=.(sm), roll=TRUE, x.sm]]
# join with CJ to ensure all levels are present
res = d[CJ(month = month, lb = mdt$sm, unique = TRUE), on=.(month, lb), .N, by=.EACHI]
# rescale to monthly pct
res[, pct := N/sum(N), by=month][]
}
# try it
f(dt1)
f(dt2)
您也可以使用 cut
执行此操作。重要的是如何对结果进行制表,而不是如何对结果进行分组...
我正在比较两年的每日土壤水分 (SM) 测量值。一年内,SM 介于 0 到 0.6 之间。
在下雨更多的另一年,SM 介于 0 到 0.8 之间。在这些数据中,我还有一些 NA's
,其中 SM 传感器由于某种原因无法工作。
让我们重新创建类似的东西:
library(data.table)
set.seed(24)
dt1 <- data.table(date=seq(as.Date("2015-01-01"), length.out=365, by="1 day"),
sm=sample(c(NA, runif(10, min=0, max=0.6)), 365, replace = TRUE))
dt2 <- data.table(date=seq(as.Date("2015-01-01"), length.out=365, by="1 day"),
sm=sample(c(NA, runif(10, min=0, max=0.8)), 365, replace = TRUE))
我正在尝试根据每个月 SM 类 之间的值比例来比较两个数据集。
我感兴趣的类是seq(0, 0.8, by=0.2)
。我还需要统计每个月测量失败的比例(NA
)。
我设法通过使用 akrun
的有用答案做到了这一点:
tmp1 <- dt1[, n := .N, month(date)][, .(perc=100 * .N/n[1]),
by=.(month=month(date),
grp=cut(sm, breaks=seq(0, 0.8, by=0.2),
labels = c('0-0.2', '0.2-0.4', '0.4-0.6', '0.6-0.8')))]
tmp2 <- dt2[, n := .N, month(date)][, .(perc=100 * .N/n[1]),
by=.(month=month(date),
grp=cut(sm, breaks=seq(0, 0.8, by=0.2),
labels = c('0-0.2', '0.2-0.4', '0.4-0.6', '0.6-0.8')))]
但是,输出并不完全符合我的预期。 由于 dt1
中的值仅介于 0 到 0.6 之间,因此结果数据中根本没有 0.6-0.8
类别 table tmp1
.
看起来 cut
忽略了最后一个类别 (0.6-0.8
),因为该范围内没有 SM 测量。这让我的比较真的很不方便,因为我在结果数据 tables tmp1
和 tmp2
.
有谁知道如何解决这个问题,即如何 "force" cut
考虑突破范围之外的值?我需要 tmp1
和 tmp2
中的所有 SM 类别,即使它们的计数为 0。
仅供参考,如果我们使用 table
,则不会发生此问题,它始终显示所有类别,即使它们的计数为零:
t1 <- runif(10, 0, 0.6)
t2 <- runif(10, 0, 0.8)
table(cut(t1, breaks=seq(0, 0.8, by=0.2)))
(0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8]
5 3 2 0
table(cut(t2, breaks=seq(0, 0.8, by=0.2)))
(0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8]
1 3 2 4
感谢任何意见。
使用CJ
计算所有级别,甚至那些没有出现在table中的级别:
f = function(d){
# create month column
d[, month := month(date)]
# roll to make cut-group column
mdt = data.table(sm = c(NA, seq(0, .8, by=.2)))
d[, lb := mdt[.SD, on=.(sm), roll=TRUE, x.sm]]
# join with CJ to ensure all levels are present
res = d[CJ(month = month, lb = mdt$sm, unique = TRUE), on=.(month, lb), .N, by=.EACHI]
# rescale to monthly pct
res[, pct := N/sum(N), by=month][]
}
# try it
f(dt1)
f(dt2)
您也可以使用 cut
执行此操作。重要的是如何对结果进行制表,而不是如何对结果进行分组...