原因是默认情况下使用NA
,它是NA_logical_
,如果根据条件只有NA
,那么它将是一个逻辑列,否则它将被强制为其他观察的列类型.如果我们使用?NA
中提到的NA_real_
常数,就可以解决这个问题
NA是长度为1的逻辑常数,其中包含缺失的值指示符.NA可以强制为除raw之外的任何其他向量类型.还有其他支持缺失值的原子向量类型的常数NA_integer_uu、NA_real_u、NA_complex_u和NA_character_u:所有这些都是R语言中的保留字.
test[, (paste0("foo", 1:3)) :=
lapply(1:3, function(x){
ifelse(get(paste0("n", x + 1)) != 0,
get(paste0("n", x))/get(paste0("n", x + 1)), NA_real_)}), by = g]
与使用ifelse
并根据列类型指定正确的NA
不同,还有一个选项是使用case_when
(从dplyr
开始)或data.table::fcase
,默认情况下返回NA(具有适当的列类型)
test[, paste0("foo", 1:3) := lapply(1:3,
function(x) fcase(.SD[[paste0("n", x + 1)]] !=0,
.SD[[paste0("n", x)]]/.SD[[paste0("n", x + 1)]])), by = g]
-测试
lst1 <- replicate(10, {
test <- data.table(v = ceiling(runif(20, 0, 5)),
g = ceiling(runif(20, 0, 2)))
setorder(test, g)
test[, (paste0("n", 1:5)) := lapply(1:5, function(x) sum(v == x)),
by = g];test[, paste0("foo", 1:3) := lapply(1:3,
function(x) fcase(.SD[[paste0("n", x + 1)]] !=0,
.SD[[paste0("n", x)]]/.SD[[paste0("n", x + 1)]])), by = g]
}, simplify = FALSE)
-用NA
判断一个元素
> lst1[[9]]
v g n1 n2 n3 n4 n5 foo1 foo2 foo3
<num> <num> <int> <int> <int> <int> <int> <num> <num> <num>
1: 4 1 3 1 0 2 4 3.00 NA 0
2: 5 1 3 1 0 2 4 3.00 NA 0
3: 1 1 3 1 0 2 4 3.00 NA 0
4: 4 1 3 1 0 2 4 3.00 NA 0
5: 5 1 3 1 0 2 4 3.00 NA 0
6: 1 1 3 1 0 2 4 3.00 NA 0
7: 5 1 3 1 0 2 4 3.00 NA 0
8: 2 1 3 1 0 2 4 3.00 NA 0
9: 1 1 3 1 0 2 4 3.00 NA 0
10: 5 1 3 1 0 2 4 3.00 NA 0
11: 2 2 1 4 0 1 4 0.25 NA 0
12: 1 2 1 4 0 1 4 0.25 NA 0
13: 2 2 1 4 0 1 4 0.25 NA 0
14: 5 2 1 4 0 1 4 0.25 NA 0
15: 5 2 1 4 0 1 4 0.25 NA 0
16: 2 2 1 4 0 1 4 0.25 NA 0
17: 5 2 1 4 0 1 4 0.25 NA 0
18: 4 2 1 4 0 1 4 0.25 NA 0
19: 2 2 1 4 0 1 4 0.25 NA 0
20: 5 2 1 4 0 1 4 0.25 NA 0
v g n1 n2 n3 n4 n5 foo1 foo2 foo3