使用线性插值法在一个变量中插值 NA 值
Interpolate NA values in one variable while using linear interpolant
尝试在数据框中插入 NA 值,并尝试使用 zoo::na.approx
但这只是 returns 等距值。
为了演示,给定数据框:
library(dplyr)
library(zoo)
df <- data.frame(
a = c(1,5 ,6 , 10),
b = c(100, NA, NA, 1000)
)
试过这个:
df %>%
mutate(b = zoo::na.approx(b, rule = 2))
而是想得到这个:
desired_df <- data.frame(
a = c(1, 5 ,6 , 10),
b = c(100, 500, 600, 1000)
)
是否有现成的函数可以做到这一点,或者必须使用线性插值公式来编写:
lin_interp <- function(known, unknown) {
# unknown object
i1 <- !is.na(unknown)
approx(x = known[i1],
y = unknown[i1],
xout = known)$y
}
提高代码的可读性
输出如愿:
df %>%
mutate(b = lin_interp(a, b))
实际上,zoo
:
desired_df <- as.zoo(df, order.by = df$a) %>%
na.approx()
如您所见,您需要将数据框转换为 zoo
class。
代码 na.approx
不起作用的原因是它通过检查 class 来分派方法。如果我们检查
library(zoo)
methods('na.approx')
#[1] na.approx.default na.approx.ts* na.approx.zoo* na.approx.zooreg*
方法 na.approx.default
是应用于 OP 数据的方法,因为它不是 zoo
对象。如果我们查看源代码,这些方法的行为是不同的
na.approx.default
和 *
函数
getAnywhere('na.approx.zoo')
所以,正如另一个答案提到的,如果我们转换为适当的 class,生成的输出也会不同,因为调度的方法是基于 class
尝试在数据框中插入 NA 值,并尝试使用 zoo::na.approx
但这只是 returns 等距值。
为了演示,给定数据框:
library(dplyr)
library(zoo)
df <- data.frame(
a = c(1,5 ,6 , 10),
b = c(100, NA, NA, 1000)
)
试过这个:
df %>%
mutate(b = zoo::na.approx(b, rule = 2))
而是想得到这个:
desired_df <- data.frame(
a = c(1, 5 ,6 , 10),
b = c(100, 500, 600, 1000)
)
是否有现成的函数可以做到这一点,或者必须使用线性插值公式来编写:
lin_interp <- function(known, unknown) {
# unknown object
i1 <- !is.na(unknown)
approx(x = known[i1],
y = unknown[i1],
xout = known)$y
}
提高代码的可读性
输出如愿:
df %>%
mutate(b = lin_interp(a, b))
实际上,zoo
:
desired_df <- as.zoo(df, order.by = df$a) %>%
na.approx()
如您所见,您需要将数据框转换为 zoo
class。
代码 na.approx
不起作用的原因是它通过检查 class 来分派方法。如果我们检查
library(zoo)
methods('na.approx')
#[1] na.approx.default na.approx.ts* na.approx.zoo* na.approx.zooreg*
方法 na.approx.default
是应用于 OP 数据的方法,因为它不是 zoo
对象。如果我们查看源代码,这些方法的行为是不同的
na.approx.default
和 *
函数
getAnywhere('na.approx.zoo')
所以,正如另一个答案提到的,如果我们转换为适当的 class,生成的输出也会不同,因为调度的方法是基于 class