R 与数据帧中最近的非NA值的距离
我有下面的dataframe df,我想为每一行添加一列,其中包含与最近的非NA值之间的距离R 与数据帧中最近的非NA值的距离,r,dataframe,R,Dataframe,我有下面的dataframe df,我想为每一行添加一列,其中包含与最近的非NA值之间的距离 df <- data.frame(x = 1:20) df[c(1, 3, 4, 5, 11, 14, 15, 16), "x"] <- NA df让x成为包含NA的向量,你的问题是 a <- which(!is.na(x)) b <- which(is.na(x)) 如果它很长并且outer的内存使用成了问题,我们可能会这样做 distance <- numeric
df <- data.frame(x = 1:20)
df[c(1, 3, 4, 5, 11, 14, 15, 16), "x"] <- NA
df让x
成为包含NA
的向量,你的问题是
a <- which(!is.na(x))
b <- which(is.na(x))
如果它很长并且outer
的内存使用成了问题,我们可能会这样做
distance <- numeric(length(x))
distance[is.na(x)] <- sapply(b, function (bi) min(abs(bi - a)))
distance这里是另一种使用rle
和rank
的方法:
library(dplyr)
library(magrittr)
df <- data.frame(x=seq(1, 20))
df[c("1", "3", "4", "5", "11", "14", "15", "16"), 1] <- NA
rle.len <- df$x %>% is.na %>% rle %$% lengths
df %>%
mutate(na.seq=rle.len %>% seq_along %>% rep(rle.len)) %>%
group_by(na.seq) %>%
mutate(distance=ifelse(is.na(x), pmin(rank(na.seq, ties.method = "first"),
rank(na.seq, ties.method = "last")), 0))
x na.seq distance
1 NA 1 1
2 2 2 0
3 NA 3 1
4 NA 3 2
5 NA 3 1
库(dplyr)
图书馆(magrittr)
df%
变异(na.seq=rle.len%%>%seq_沿%>%rep(rle.len))%%>%
分组依据(不适用序号)%>%
突变(距离=ifelse(is.na(x),pmin(秩(na.seq,ties.method=“first”),
排名(na.seq,ties.method=“last”)),0)
x na.seq距离
1 NA 11
2 2 2 0
3 NA 3 1
4 NA 3 2
5 NA 3 1
您可以使用findInterval
。首先,找到NA
和非NA
值的索引,并初始化距离列:
na <- which(is.na(df$x))
non_na <- which(!is.na(df$x))
df$distance2 <- 0
一种方法是在使用包将矩阵转换为光栅层对象后,在包中使用
该软件包适用于地图,因此当您使用光栅()
时,对象将具有单位、分辨率等。因此,当您使用距离()
时,对于与非NA(我是15796.35)相距一米的元素,距离可能非常大。只需除以这个数量(由于舍入错误,可能是round()
)就可以得到你的答案
例如,如果我有一个名为a1
的NAs数组对象:
> a1 = array(
c(
c(1, 5, 6, NA, 1, 2, 5),
c(3, 4, NA, NA, NA, 8, 1),
c(5, 1, 7, NA, 2, 3, 7),
c(8, 1, 1, 2, 3, 6, 2)
),
c(7, 4)
)
> r1 = raster(a1)
> d1 = distance(r1)
> as.matrix(d1)
[,1] [,2] [,3] [,4]
[1,] 0.00 0.00 0.00 0
[2,] 0.00 0.00 0.00 0
[3,] 0.00 15796.35 0.00 0
[4,] 15796.33 31592.66 15796.33 0
[5,] 0.00 15796.33 0.00 0
[6,] 0.00 0.00 0.00 0
[7,] 0.00 0.00 0.00 0
> round(
as.matrix(d1) / 15796.35,
0
)
[,1] [,2] [,3] [,4]
[1,] 0 0 0 0
[2,] 0 0 0 0
[3,] 0 1 0 0
[4,] 1 2 1 0
[5,] 0 1 0 0
[6,] 0 0 0 0
[7,] 0 0 0 0
这是你的答案。不过,我不知道distance()
函数背后的代码有多高效,所以我不知道这是否需要一段时间
编辑:在具有29000 NAs的阵列对象上进行测试,需要很长时间。我建议您只对NAs较少的对象使用此选项。我有20000行。应该很好,谢谢。我刚刚注意到,对于在最后一行中使用NAs完成数据帧的情况,您的方法将不起作用。它将考虑从非NA值的距离为1的最后一行(NA)。
na <- which(is.na(df$x))
non_na <- which(!is.na(df$x))
df$distance2 <- 0
df$distance2[na] <- abs(na - non_na[findInterval(na, (non_na[-length(non_na)] + non_na[-1]) / 2) + 1])
df
# x distance distance2
# 1 NA 1 1
# 2 2 0 0
# 3 NA 1 1
# 4 NA 2 2
# 5 NA 1 1
# 6 6 0 0
# 7 7 0 0
# 8 8 0 0
# 9 9 0 0
# 10 10 0 0
# 11 NA 1 1
# 12 12 0 0
# 13 13 0 0
# 14 NA 1 1
# 15 NA 2 2
# 16 NA 1 1
# 17 17 0 0
# 18 18 0 0
# 19 19 0 0
# 20 20 0 0
> a1 = array(
c(
c(1, 5, 6, NA, 1, 2, 5),
c(3, 4, NA, NA, NA, 8, 1),
c(5, 1, 7, NA, 2, 3, 7),
c(8, 1, 1, 2, 3, 6, 2)
),
c(7, 4)
)
> r1 = raster(a1)
> d1 = distance(r1)
> as.matrix(d1)
[,1] [,2] [,3] [,4]
[1,] 0.00 0.00 0.00 0
[2,] 0.00 0.00 0.00 0
[3,] 0.00 15796.35 0.00 0
[4,] 15796.33 31592.66 15796.33 0
[5,] 0.00 15796.33 0.00 0
[6,] 0.00 0.00 0.00 0
[7,] 0.00 0.00 0.00 0
> round(
as.matrix(d1) / 15796.35,
0
)
[,1] [,2] [,3] [,4]
[1,] 0 0 0 0
[2,] 0 0 0 0
[3,] 0 1 0 0
[4,] 1 2 1 0
[5,] 0 1 0 0
[6,] 0 0 0 0
[7,] 0 0 0 0