用均匀增长的中间值桥接最后一个和下一个非 NA 值
Bridge the last and next non-NA value with intermediate values that grow evenly
用从最后一个非 NA 值逐渐增长到下一个非 NA 值的中间值填充数据框列中缺失的 NA 的好方法是什么?
这是一个示例:对于列成本,我想获得列 cost_esti,其中成本在 2014 年和 2016 年之间每年增加 31 美元,将上一个已知的 595 美元成本与下一个成本相结合已知成本 720 美元
我想出的代码很长。有没有一种优雅的方法可以做到这一点?
library(data.table)
data = data.table(year=2000:2018,
cost = c(100,120,NA,200,220,NA,NA,300,350,470,500,NA,NA,595,NA,NA,NA,720,800))
data[,cost_nas:=as.numeric(is.na(cost))]
## consecutive nas so far for each row:
data[, consecutive_nas_so_far := seq_len(.N), by=rleid(cost_nas)]
data[cost_nas==0,consecutive_nas_so_far:=0]
# total number of consecutive nas in the sequence
data[,total_number_of_consec_nas:=ifelse(consecutive_nas_so_far>0&shift(consecutive_nas_so_far,1,type = "lead")==0,consecutive_nas_so_far,NA)]
data[cost_nas==0,total_number_of_consec_nas:=0]
data[,total_number_of_consec_nas:=zoo::na.locf(total_number_of_consec_nas,fromLast=T)]
#get last and next known values for cost:
data[,cost_previous:=zoo::na.locf(cost)]
data[,cost_following:=zoo::na.locf(cost,fromLast=T)]
# apply the formula to calculate the gradual increase from cost_previous to cost_following
data[,cost_esti:=round(consecutive_nas_so_far*(cost_following-cost_previous)/(total_number_of_consec_nas+1)+cost_previous,0)]
data[is.na(cost_esti),cost_esti:=cost]
您可以使用 zoo::na.locf
和 data.table::rleid
re-write
data.table 操作。使用 na.locf
添加 2 列,lastNonNA
和 nextNonNA
各一列。 rleid
将为您提供连续 NA
的不同组别。现在您可以编写逻辑以在 lastNonNA
和 nextNonNA
.
之间使用 linear
填充 NA
library(data.table)
library(zoo)
#Data
data = data.table(year=2000:2018,
cost = c(100,120,NA,200,220,NA,NA,300,350,470,500,NA,NA,595,NA,NA,NA,720,800))
data[,':='(lastNonNA = na.locf(cost, fromLast = FALSE),
nextNonNA = na.locf(cost, fromLast = TRUE), Group_NA = rleid(is.na(cost)))][
,':='(IDX = 1:.N), by=Group_NA][
,':='(cost = ifelse(is.na(cost), lastNonNA + IDX*((nextNonNA - lastNonNA)/(.N+1)),cost)),
by=Group_NA][,.(year, cost)]
# year cost
# 1: 2000 100.0000
# 2: 2001 120.0000
# 3: 2002 160.0000 #Filled
# 4: 2003 200.0000
# 5: 2004 220.0000
# 6: 2005 246.6667 #Filled
# 7: 2006 273.3333 #Filled
# 8: 2007 300.0000
# 9: 2008 350.0000
# 10: 2009 470.0000
# 11: 2010 500.0000
# 12: 2011 531.6667 #Filled
# 13: 2012 563.3333 #Filled
# 14: 2013 595.0000
# 15: 2014 626.2500 #Filled
# 16: 2015 657.5000 #Filled
# 17: 2016 688.7500 #Filled
# 18: 2017 720.0000
# 19: 2018 800.0000
你问的问题是线性插值。
可以很容易地在 R 中为您的数据获得 NAs。
在这种情况下,解决方案是:
library("imputeTS")
na_interpolation(data, option = "linear")
您也可以使用 option = "spline" 或 "stine" 那么增加不一定是严格线性的。
用从最后一个非 NA 值逐渐增长到下一个非 NA 值的中间值填充数据框列中缺失的 NA 的好方法是什么?
这是一个示例:对于列成本,我想获得列 cost_esti,其中成本在 2014 年和 2016 年之间每年增加 31 美元,将上一个已知的 595 美元成本与下一个成本相结合已知成本 720 美元
我想出的代码很长。有没有一种优雅的方法可以做到这一点?
library(data.table)
data = data.table(year=2000:2018,
cost = c(100,120,NA,200,220,NA,NA,300,350,470,500,NA,NA,595,NA,NA,NA,720,800))
data[,cost_nas:=as.numeric(is.na(cost))]
## consecutive nas so far for each row:
data[, consecutive_nas_so_far := seq_len(.N), by=rleid(cost_nas)]
data[cost_nas==0,consecutive_nas_so_far:=0]
# total number of consecutive nas in the sequence
data[,total_number_of_consec_nas:=ifelse(consecutive_nas_so_far>0&shift(consecutive_nas_so_far,1,type = "lead")==0,consecutive_nas_so_far,NA)]
data[cost_nas==0,total_number_of_consec_nas:=0]
data[,total_number_of_consec_nas:=zoo::na.locf(total_number_of_consec_nas,fromLast=T)]
#get last and next known values for cost:
data[,cost_previous:=zoo::na.locf(cost)]
data[,cost_following:=zoo::na.locf(cost,fromLast=T)]
# apply the formula to calculate the gradual increase from cost_previous to cost_following
data[,cost_esti:=round(consecutive_nas_so_far*(cost_following-cost_previous)/(total_number_of_consec_nas+1)+cost_previous,0)]
data[is.na(cost_esti),cost_esti:=cost]
您可以使用 zoo::na.locf
和 data.table::rleid
re-write
data.table 操作。使用 na.locf
添加 2 列,lastNonNA
和 nextNonNA
各一列。 rleid
将为您提供连续 NA
的不同组别。现在您可以编写逻辑以在 lastNonNA
和 nextNonNA
.
linear
填充 NA
library(data.table)
library(zoo)
#Data
data = data.table(year=2000:2018,
cost = c(100,120,NA,200,220,NA,NA,300,350,470,500,NA,NA,595,NA,NA,NA,720,800))
data[,':='(lastNonNA = na.locf(cost, fromLast = FALSE),
nextNonNA = na.locf(cost, fromLast = TRUE), Group_NA = rleid(is.na(cost)))][
,':='(IDX = 1:.N), by=Group_NA][
,':='(cost = ifelse(is.na(cost), lastNonNA + IDX*((nextNonNA - lastNonNA)/(.N+1)),cost)),
by=Group_NA][,.(year, cost)]
# year cost
# 1: 2000 100.0000
# 2: 2001 120.0000
# 3: 2002 160.0000 #Filled
# 4: 2003 200.0000
# 5: 2004 220.0000
# 6: 2005 246.6667 #Filled
# 7: 2006 273.3333 #Filled
# 8: 2007 300.0000
# 9: 2008 350.0000
# 10: 2009 470.0000
# 11: 2010 500.0000
# 12: 2011 531.6667 #Filled
# 13: 2012 563.3333 #Filled
# 14: 2013 595.0000
# 15: 2014 626.2500 #Filled
# 16: 2015 657.5000 #Filled
# 17: 2016 688.7500 #Filled
# 18: 2017 720.0000
# 19: 2018 800.0000
你问的问题是线性插值。 可以很容易地在 R 中为您的数据获得 NAs。
在这种情况下,解决方案是:
library("imputeTS")
na_interpolation(data, option = "linear")
您也可以使用 option = "spline" 或 "stine" 那么增加不一定是严格线性的。