用时间序列或同一列中的相邻值替换 NA 值 - data.table 方法
Replace NA values with adjacent value in the time series or in the same column - data.table method
示例数据
df <- data.frame(id=c("A","A","A","A","B","B","B","B"),year=c(2014,2014,2015,2015),month=c(1,2),marketcap=c(4,6,2,6,23,2,5,34),return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6))
df1
id year month marketcap return
1: A 2014 1 4 NA
2: A 2014 2 6 0.23
3: A 2015 1 2 0.20
4: A 2015 2 6 0.10
5: B 2014 1 23 0.40
6: B 2014 2 2 0.90
7: B 2015 1 5 NA
8: B 2015 2 34 0.60
需要的数据
desired_df <- data.frame(id=c("A","A","A","A","B","B","B","B"),year=c(2014,2014,2015,2015),month=c(1,2),marketcap=c(4,6,2,6,23,2,5,34),return=c(0.23,0.23,0.2,0.1,0.4,0.9,0.75,0.6))
desired_df
id year month marketcap return
1 A 2014 1 4 0.23
2 A 2014 2 6 0.23
3 A 2015 1 2 0.20
4 A 2015 2 6 0.10
5 B 2014 1 23 0.40
6 B 2014 2 2 0.90
7 B 2015 1 5 0.75
8 B 2015 2 34 0.60
我想通过 id 将 NA
值替换为时间序列中的相邻值来插入 return。假设只有两个月:一年中有 1,2 个月。
(B,2015,1) 的第二个 NA
替换为 0.75 =(0.9+0.6)/2
(A,2014,1) 的第一个 NA
替换为 0.23,因为没有以前的数据。
data.table 如果可能的话,最好解决方案
更新:
当使用如下代码结构时(适用于示例)
df[,returnInterpolate:=na.approx(return,rule=2), by=id]
我遇到了错误:
大约 (x[!na], y[!na], xout, ...) 中的错误:
需要至少两个非 NA 值进行插值
我想可能有一些 id 没有非 NA 值可以插入。 。有什么建议么?
library(data.table)
df <- data.frame(id=c("A","A","A","A","B","B","B","B"),
year=c(2014,2014,2015,2015),
month=c(1,2),
marketcap=c(4,6,2,6,23,2,5,34),
return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6))
setDT(df)
library(zoo)
df[, returnInterpol := na.approx(return, rule = 2), by = id]
# id year month marketcap return returnInterpol
#1: A 2014 1 4 NA 0.23
#2: A 2014 2 6 0.23 0.23
#3: A 2015 1 2 0.20 0.20
#4: A 2015 2 6 0.10 0.10
#5: B 2014 1 23 0.40 0.40
#6: B 2014 2 2 0.90 0.90
#7: B 2015 1 5 NA 0.75
#8: B 2015 2 34 0.60 0.60
编辑:
如果您的组只有 NA
个值或只有一个非 NA
,您可以这样做:
df <- data.frame(id=c("A","A","A","A","B","B","B","B","C","C","C","C"),
year=c(2014,2014,2015,2015),
month=c(1,2),
marketcap=c(4,6,2,6,23,2,5,34, 1:4),
return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6,NA,NA,0.3,NA))
setDT(df)
df[, returnInterpol := switch(as.character(sum(!is.na(return))),
"0" = return,
"1" = {na.omit(return)},
na.approx(return, rule = 2)), by = id]
# id year month marketcap return returnInterpol
# 1: A 2014 1 4 NA 0.23
# 2: A 2014 2 6 0.23 0.23
# 3: A 2015 1 2 0.20 0.20
# 4: A 2015 2 6 0.10 0.10
# 5: B 2014 1 23 0.40 0.40
# 6: B 2014 2 2 0.90 0.90
# 7: B 2015 1 5 NA 0.75
# 8: B 2015 2 34 0.60 0.60
# 9: C 2014 1 1 NA 0.30
# 10: C 2014 2 2 NA 0.30
# 11: C 2015 1 3 0.30 0.30
# 12: C 2015 2 4 NA 0.30
不关心 ID 的简单 imputeTS
解决方案是:
library("imputeTS")
na.interpolate(df)
由于应该根据 ID 进行插补,因此有点复杂 - 因为当按 ID 过滤时,似乎经常没有足够的值剩余。我会采用 Roland 发布的解决方案并在可能的情况下使用 imputeTS::na.interpolation()
,在其他情况下,可能使用 imputeTS::na.mean()
的总体平均值或总体范围中的随机猜测 imputeTS::na.random()
可以使用。
在这种情况下,超越单变量时间序列插值/插补也可能是一个很好的主意。还有很多其他变量可以帮助估计缺失值(如果存在相关性)。像 AMELIA
这样的软件包可以在这里提供帮助。
示例数据
df <- data.frame(id=c("A","A","A","A","B","B","B","B"),year=c(2014,2014,2015,2015),month=c(1,2),marketcap=c(4,6,2,6,23,2,5,34),return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6))
df1
id year month marketcap return
1: A 2014 1 4 NA
2: A 2014 2 6 0.23
3: A 2015 1 2 0.20
4: A 2015 2 6 0.10
5: B 2014 1 23 0.40
6: B 2014 2 2 0.90
7: B 2015 1 5 NA
8: B 2015 2 34 0.60
需要的数据
desired_df <- data.frame(id=c("A","A","A","A","B","B","B","B"),year=c(2014,2014,2015,2015),month=c(1,2),marketcap=c(4,6,2,6,23,2,5,34),return=c(0.23,0.23,0.2,0.1,0.4,0.9,0.75,0.6))
desired_df
id year month marketcap return
1 A 2014 1 4 0.23
2 A 2014 2 6 0.23
3 A 2015 1 2 0.20
4 A 2015 2 6 0.10
5 B 2014 1 23 0.40
6 B 2014 2 2 0.90
7 B 2015 1 5 0.75
8 B 2015 2 34 0.60
我想通过 id 将 NA
值替换为时间序列中的相邻值来插入 return。假设只有两个月:一年中有 1,2 个月。
(B,2015,1) 的第二个 NA
替换为 0.75 =(0.9+0.6)/2
(A,2014,1) 的第一个 NA
替换为 0.23,因为没有以前的数据。
data.table 如果可能的话,最好解决方案
更新: 当使用如下代码结构时(适用于示例)
df[,returnInterpolate:=na.approx(return,rule=2), by=id]
我遇到了错误: 大约 (x[!na], y[!na], xout, ...) 中的错误: 需要至少两个非 NA 值进行插值
我想可能有一些 id 没有非 NA 值可以插入。 。有什么建议么?
library(data.table)
df <- data.frame(id=c("A","A","A","A","B","B","B","B"),
year=c(2014,2014,2015,2015),
month=c(1,2),
marketcap=c(4,6,2,6,23,2,5,34),
return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6))
setDT(df)
library(zoo)
df[, returnInterpol := na.approx(return, rule = 2), by = id]
# id year month marketcap return returnInterpol
#1: A 2014 1 4 NA 0.23
#2: A 2014 2 6 0.23 0.23
#3: A 2015 1 2 0.20 0.20
#4: A 2015 2 6 0.10 0.10
#5: B 2014 1 23 0.40 0.40
#6: B 2014 2 2 0.90 0.90
#7: B 2015 1 5 NA 0.75
#8: B 2015 2 34 0.60 0.60
编辑:
如果您的组只有 NA
个值或只有一个非 NA
,您可以这样做:
df <- data.frame(id=c("A","A","A","A","B","B","B","B","C","C","C","C"),
year=c(2014,2014,2015,2015),
month=c(1,2),
marketcap=c(4,6,2,6,23,2,5,34, 1:4),
return=c(NA,0.23,0.2,0.1,0.4,0.9,NA,0.6,NA,NA,0.3,NA))
setDT(df)
df[, returnInterpol := switch(as.character(sum(!is.na(return))),
"0" = return,
"1" = {na.omit(return)},
na.approx(return, rule = 2)), by = id]
# id year month marketcap return returnInterpol
# 1: A 2014 1 4 NA 0.23
# 2: A 2014 2 6 0.23 0.23
# 3: A 2015 1 2 0.20 0.20
# 4: A 2015 2 6 0.10 0.10
# 5: B 2014 1 23 0.40 0.40
# 6: B 2014 2 2 0.90 0.90
# 7: B 2015 1 5 NA 0.75
# 8: B 2015 2 34 0.60 0.60
# 9: C 2014 1 1 NA 0.30
# 10: C 2014 2 2 NA 0.30
# 11: C 2015 1 3 0.30 0.30
# 12: C 2015 2 4 NA 0.30
不关心 ID 的简单 imputeTS
解决方案是:
library("imputeTS")
na.interpolate(df)
由于应该根据 ID 进行插补,因此有点复杂 - 因为当按 ID 过滤时,似乎经常没有足够的值剩余。我会采用 Roland 发布的解决方案并在可能的情况下使用 imputeTS::na.interpolation()
,在其他情况下,可能使用 imputeTS::na.mean()
的总体平均值或总体范围中的随机猜测 imputeTS::na.random()
可以使用。
在这种情况下,超越单变量时间序列插值/插补也可能是一个很好的主意。还有很多其他变量可以帮助估计缺失值(如果存在相关性)。像 AMELIA
这样的软件包可以在这里提供帮助。