Roll join 在 data.table 中不给出 NA 值
Roll join does not give NA values in data.table
假设我有以下数据:
library(data.table)
x1 <- structure(list(age = c(NA, 40L, 78L, 49L, 59L),
age_cat = c(NA, "(39,50]", "(72,83]", "(39,50]", "(57,64]")),
row.names = c(NA, -5L), class = c("data.table", "data.frame"))
x2 <- structure(list(age = c(20.5, 25.5, 30.5, 35.5, 40.5, 45.5, 50.5,
55.5, 60.5, 65.5, 70.5, 75.5, 80.5, 85.5, 90.5),
yhat = c(2.04759618619815, 1.48463998876167,
1.20171574722936, 1.05038762605566,
1.00519209126108, 0.996948029536619,
0.945501768666378, 0.834241582084186,
0.731586245690655, 0.727522200367293,
0.816133858934611, 0.817941581611403,
0.498731829342745, 0.104433989674483,
1.59446835516229)),
row.names = c(NA, -15L),
class = "data.frame")
然后创建一个函数来加入最接近的年龄:
join_nearest <- function(dat, reference, x){
reference <- data.table::data.table(reference)
dat <- data.table::data.table(dat)
join <- reference[dat, roll = "nearest", on = x]
as.data.frame(join)
}
这给出了以下解决方案:
join_nearest(x1, x2, "age")
#> age yhat age_cat
#> 1 NA 2.0475962 <NA>
#> 2 40 1.0051921 (39,50]
#> 3 78 0.8179416 (72,83]
#> 4 49 0.9455018 (39,50]
#> 5 59 0.7315862 (57,64]
如果 age
等于 NA 我期望 yhat
也等于 NA。我想知道为什么不是这种情况,有没有办法 return NA 对于 age
等于 NA 的行?
由 reprex package (v2.0.1)
于 2021-11-10 创建
您可以进行基于范围的手动联接。
前面:x1$age
是整数,但 x2$age
是数字,所以我会将第一个转换为 numeric
,这样 data.table 就不会抱怨 class.
然后,我将在 x2
中创建 lo/hi 个字段,我们可以使用这些字段加入。如果你更喜欢断点不是中途,这很容易改变,根据你的需要。
x1[, age := as.numeric(age)]
x1[x2[, c("lo","hi") := .(age - c(age[1],diff(age)/2), age + c(diff(age)/2,Inf))
], yhat := i.yhat, on = .(age >= lo, age < hi),
][]
# age age_cat yhat
# <num> <char> <num>
# 1: NA <NA> NA
# 2: 40 (39,50] 1.0051921
# 3: 78 (72,83] 0.4987318
# 4: 49 (39,50] 0.9455018
# 5: 59 (57,64] 0.7315862
## cleanup
x2[, c("lo","hi") := NULL]
我认识到添加 lo
和 hi
的暂时副作用,因此需要清理。如果您的数据不大,您可以使用 copy(x2)[,c("lo","hi"):=...]
来避免这种情况,但会降低内存效率。
假设我有以下数据:
library(data.table)
x1 <- structure(list(age = c(NA, 40L, 78L, 49L, 59L),
age_cat = c(NA, "(39,50]", "(72,83]", "(39,50]", "(57,64]")),
row.names = c(NA, -5L), class = c("data.table", "data.frame"))
x2 <- structure(list(age = c(20.5, 25.5, 30.5, 35.5, 40.5, 45.5, 50.5,
55.5, 60.5, 65.5, 70.5, 75.5, 80.5, 85.5, 90.5),
yhat = c(2.04759618619815, 1.48463998876167,
1.20171574722936, 1.05038762605566,
1.00519209126108, 0.996948029536619,
0.945501768666378, 0.834241582084186,
0.731586245690655, 0.727522200367293,
0.816133858934611, 0.817941581611403,
0.498731829342745, 0.104433989674483,
1.59446835516229)),
row.names = c(NA, -15L),
class = "data.frame")
然后创建一个函数来加入最接近的年龄:
join_nearest <- function(dat, reference, x){
reference <- data.table::data.table(reference)
dat <- data.table::data.table(dat)
join <- reference[dat, roll = "nearest", on = x]
as.data.frame(join)
}
这给出了以下解决方案:
join_nearest(x1, x2, "age")
#> age yhat age_cat
#> 1 NA 2.0475962 <NA>
#> 2 40 1.0051921 (39,50]
#> 3 78 0.8179416 (72,83]
#> 4 49 0.9455018 (39,50]
#> 5 59 0.7315862 (57,64]
如果 age
等于 NA 我期望 yhat
也等于 NA。我想知道为什么不是这种情况,有没有办法 return NA 对于 age
等于 NA 的行?
由 reprex package (v2.0.1)
于 2021-11-10 创建您可以进行基于范围的手动联接。
前面:x1$age
是整数,但 x2$age
是数字,所以我会将第一个转换为 numeric
,这样 data.table 就不会抱怨 class.
然后,我将在 x2
中创建 lo/hi 个字段,我们可以使用这些字段加入。如果你更喜欢断点不是中途,这很容易改变,根据你的需要。
x1[, age := as.numeric(age)]
x1[x2[, c("lo","hi") := .(age - c(age[1],diff(age)/2), age + c(diff(age)/2,Inf))
], yhat := i.yhat, on = .(age >= lo, age < hi),
][]
# age age_cat yhat
# <num> <char> <num>
# 1: NA <NA> NA
# 2: 40 (39,50] 1.0051921
# 3: 78 (72,83] 0.4987318
# 4: 49 (39,50] 0.9455018
# 5: 59 (57,64] 0.7315862
## cleanup
x2[, c("lo","hi") := NULL]
我认识到添加 lo
和 hi
的暂时副作用,因此需要清理。如果您的数据不大,您可以使用 copy(x2)[,c("lo","hi"):=...]
来避免这种情况,但会降低内存效率。