r语言 - tidyr::complete的行为取决于列类和舍入规范



我有一个湖泊中许多不同站点的深度数据帧,我希望每个站点都有从最小到最大的完整深度序列(以及用NAs填充的缺失值)。

我使用tidyr::complete来做这个,但是它的行为很奇怪。当深度四舍五入到小数点后0位时,代码按预期运行,但是当数据到十分之一米时,深度类发生了一些奇怪的事情,并且完成了一些组合(并且值填充了NA),即使我已经有了该深度的数据。

有人经历过这种情况吗?我认为它与深度类有关,但我还没有完全弄清楚它或如何避免它。

library(dplyr)
b <- data.frame(site = c(rep("A", 10), rep("B", 10)),
depth = c(seq(0.1, 0.8, 0.1), 1.0, 1.1, seq(0.3, 0.5, 0.1), seq(0.9, 1.5, 0.1)),
value = round(runif(20, 0, 5), 1))
b2 <- b %>% 
mutate(site = factor(site)) %>% 
group_by(site) %>% 
tidyr::complete(depth = seq(min(depth),
max(depth),
by = 0.1)) %>% 
arrange(site, depth)

原始数据帧的一些深度被复制,这是意想不到的。

class(b2$depth) 
unique(b2$depth)
b2[b2$site == "B", ] 

当我从数字转换回数字时,深度似乎已经恢复到我所期望的,尽管我仍然需要用NAs删除重复的深度。

class(as.numeric(as.character(b2$depth))) 
unique(as.numeric(as.character(b2$depth)))

如果深度没有小数点,行为似乎更容易预测。

a <- data.frame(site = c(rep("A", 10), rep("B", 10)),
depth = c(1:4, 6:11, 3:5, 8, 10, 12:16),
value = round(runif(20, 0, 5), 1))
a2 <- a %>% 
mutate(site = factor(site)) %>% 
group_by(site) %>% 
tidyr::complete(depth = seq(min(depth),
max(depth),
by = 1)) %>% 
arrange(site, depth)
class(a2$depth)
unique(a2$depth)
a2[a2$site == "B", ] 

确实,complete()正在产生额外的无法解释的元素。

我认为,当complete()匹配序列产生的数字和原始数据中的数字时,它将(1.4 == 1.4)计算为FALSE并将它们作为两个不同的数字返回。我做了一个小测试,我确实得到了FALSE!为了避免这种情况,我们需要四舍五入,并确保"深度"值在原dataframe和那些由seq()是相同的。

b <- data.frame(site = c(rep("A", 10), rep("B", 10)),
depth = c(seq(0.1, 0.8, 0.1), 1.0, 1.1, seq(0.3, 0.5, 0.1), seq(0.9, 1.5, 0.1)),
value = round(runif(20, 0, 5), 1))
b$depth <- round(b$depth,2) #crucial to do it here and not via mutate()
b2 <- b %>%
mutate(site = factor(site)) %>%
group_by(site) %>% 
tidyr::complete(depth = round(seq(min(depth),
max(depth),
by = 0.1), 
2)) %>% 
ungroup() 

检查B站点的输出是否正常

> b2[b2$site == "B",]
# A tibble: 13 × 3
site  depth value
<chr> <chr> <dbl>
1 B     0.3     3.4
2 B     0.4     0.7
3 B     0.5     4.5
4 B     0.6    NA  
5 B     0.7    NA  
6 B     0.8    NA  
7 B     0.9     1.4
8 B     1       1.2
9 B     1.1     1.3
10 B     1.2     3.3
11 B     1.3     2.1
12 B     1.4     0.9
13 B     1.5     1.2

这个问题,据我所知,是由于seq()商店它生成的值。注意这些值是如何不精确的:

> v2 = seq(.3,1.4, by = .1)
> print(v2, digits =16)
[1] 0.3000000000000000 0.4000000000000000 0.5000000000000000 0.6000000000000001
[5] 0.7000000000000000 0.8000000000000000 0.9000000000000001 1.0000000000000000
[9] 1.1000000000000001 1.2000000000000000 1.3000000000000000 1.3999999999999999

1.3999以来……不等于1.4,则complete()没有将两个1.4的值连接起来。这就是副本产生的原因。

最新更新