目前,我正在尝试在R中的向量中估算值。 归因于。
# example one
input_one = c(1,NA,3,4,NA,6,NA,NA)
# example two
input_two = c(NA,NA,3,4,5,6,NA,NA)
# example three
input_three = c(NA,NA,3,4,NA,6,NA,NA)
我开始编写代码以检测可以 被推算。但是我坚持以下几点。
# incomplete function to detect the values
sapply(split(!is.na(input[c(rbind(which(is.na(c(input)))-1, which(is.na(c(input)))+1))]),
rep(1:(length(!is.na(input[c(which(is.na(c(input)))-1, which(is.na(c(input)))+1)]))/2), each = 2)), all)
但是,这仅检测到可能是 可归因的,并且仅适用于示例一。它不完整且 不幸的是,它很难阅读和理解。
任何对此的帮助将不胜感激。
答案 0 :(得分:1)
我们可以使用dplyr
的{{1}}和lag
函数:
lead
拒绝:
input_three = c(NA,NA,3,4,NA,6,NA,NA)
library(dplyr)
ifelse(is.na(input_three) & lead(input_three) > lag(input_three),
(lag(input_three) + lead(input_three))/ 2,
input_three)
说明:
我们使用[1] NA NA 3 4 5 6 NA NA
的向量化版本ifelse
。即if
中的所有内容都将应用于向量的每个元素。
首先,我们测试元素是否为ifelse
,以及后面的元素是否大于前一个元素。要获取上一个和下一个元素,我们可以使用NA
dplyr
和lead
函数:
lag
使向量向右偏移(默认为1步):
lag
返回:
lag(1:5)
[1] NA 1 2 3 4
将向量向左偏移:
lead
返回:
lead(1:5)
现在进入[1] 2 3 4 5 NA
的'test'子句:
ifelse
哪个返回:
is.na(input_three) & lead(input_three) > lag(input_three)
然后,如果[1] NA NA FALSE FALSE TRUE FALSE NA NA
子句的值为ifelse
,我们要返回上一个元素和下一个元素的和除以2,否则返回原始元素
答案 1 :(得分:1)
下面是使用imputeTS
库的示例。它考虑了序列中的多个NA
,如果下一个有效观测值大于最后一个有效观测值,则确保计算平均值,并且在开始和结束时都忽略NA
。>
library(imputeTS)
myimpute <- function(series) {
# Find where each NA is
nalocations <- is.na(series)
# Find the last and the previous observation for each row
last1 <- lag(series)
next1 <- lead(series)
# Carry forward the last and next observations over sequences of NA
# Each row will then get a last and next that can be averaged
cflast <- na_locf(last1, na_remaining = 'keep')
cfnext <- na_locf(next1, option = 'nocb', na_remaining = 'keep')
# Make a data frame
df <- data.frame(series, nalocations, last1, cflast, next1, cfnext)
# Calculate the mean where there is currently a NA
# making sure that the next is greater than the last
df$mean <- ifelse(df$nalocations, ifelse(df$cflast < df$cfnext, (df$cflast+df$cfnext)/2, NA), NA)
imputedseries <- ifelse(df$nalocations, ifelse(!is.na(df$mean), df$mean, NA), series)
#list(df, imputedseries) # comment this in and return it to see the intermediate data frame for debugging
imputedseries
}
myimpute(c(NA,NA,3,4,NA,NA,6,NA,NA,8,NA,7,NA,NA,9,NA,11,NA,NA))
# [1] NA NA 3 4 5 5 6 7 7 8 NA 7 8 8 9 10 11 NA NA
答案 2 :(得分:0)
以下是使用zoo::rollapply()
的替代方法:
library(zoo)
fill_sandwiched_na <- function(f) rollapply(f, 3, FUN = function(x) {
y <- mean(x[-2]); if(is.na(y)) x[2] else y
}, fill = NA, partial = TRUE)
fill_sandwiched_na(input_one)
[1] 1 2 3 4 5 6 NA NA
fill_sandwiched_na(input_two)
[1] NA NA 3 4 5 6 NA NA
fill_sandwiched_na(input_three)
[1] NA NA 3 4 5 6 NA NA
答案 3 :(得分:0)
imputeTS 软件包中还包含na_ma
函数,用于估算移动平均值。
在您的情况下,将使用以下设置:
na_ma(x, k = 1, weighting = "simple")
基本上只需一行代码即可轻松实现:
library(imputeTS)
na_ma(yourData, k = 1, weighting = "simple")
您还可以选择在NA之前和之后考虑更多的值,例如k = 3。如果您考虑到每一侧的值都超过1,则有趣的功能是可以选择其他权重,例如权重=“线性”时,权重在算术级数中减少(线性加权移动平均值)-表示它们的值越远离NA,其影响就越小。