如何使用R对日期进行值的外推

3

我有一年中前7个月的数据,并希望线性外推下5个月的数据。我尝试使用Hmisc软件包中的approxExtrap函数,但不确定如何使用,特别是xout参数应该指定什么。如果可能,基于dplyr的解决方案将是理想的。感谢您的时间。

以下是数据示例:


df <- tibble(pop = c(18968, 18956, 18946, 18934, 18923, 18912, 18901, NA, NA, NA, NA, NA),
                       date = c("2020-01-01", "2020-02-01", "2020-03-01", 
                                "2020-04-01", "2020-05-01", "2020-06-01", 
                                "2020-07-01", "2020-08-01", "2020-09-01", 
                                "2020-10-01", "2020-11-01", "2020-12-01"))
df$date <- lubridate::as_date(df$date)

3个回答

2
运行lmpredict,然后使用coalesce将已知值和预测值组合在一起。
library(dplyr)
df %>%
  mutate(pop2 = coalesce(pop, predict(lm(pop ~ date), across(date))))

给定以下内容,其中pop2是用预测值填充了NA的pop
# A tibble: 12 × 3
     pop date         pop2
   <dbl> <date>      <dbl>
 1 18968 2020-01-01 18968 
 2 18956 2020-02-01 18956 
 3 18946 2020-03-01 18946 
 4 18934 2020-04-01 18934 
 5 18923 2020-05-01 18923 
 6 18912 2020-06-01 18912 
 7 18901 2020-07-01 18901 
 8    NA 2020-08-01 18889.
 9    NA 2020-09-01 18878.
10    NA 2020-10-01 18867.
11    NA 2020-11-01 18856.
12    NA 2020-12-01 18845.

谢谢。我喜欢这个解决方案,但是我意识到我的问题没有反映出我真正需要的东西。我已经在这里发布了一个后续问题(https://stackoverflow.com/questions/74867473/linear-interpolating-and-extrapolating-across-dates-in-r)。当我尝试在我的当前数据中实现它时(我在链接的问题中分享),出现了一些问题,预测值与实际数据不一致。 - dd_data
当我使用你在其他帖子里提供的数据运行这个答案中的代码时,直线穿过了数据点,因此要么你犯了一个错误,要么数据并不能很好地代表你所拥有的内容。对于你展示的数据,以下内容是不需要的,但如果你想尝试其他方法,请使用zoo包中的na.approx来填充内部NA,然后在这里使用外推法来填充其余部分。 - G. Grothendieck
你说得对。我现在明白了,当我有超过2个实际数据点时问题就会出现。我已经更新了问题以反映这一点。再次感谢你。 - dd_data
尝试使用library(zoo); df %>% mutate(pop2 = na.spline(pop, date)) - G. Grothendieck
谢谢 - 最好的方法是使用na.approx来填充内部值,然后使用na.spline来填充少量的外部值。当只需要从一个点进行外推时,na.spline似乎是线性外推,这正是我想要的。 - dd_data

2
如果您想要进行线性插值,lm将创建一个拟合对象,您可以从中进行预测。 na是传递给predict.lm作为参数newdata的新数据。
df <- data.frame(pop = c(18968, 18956, 18946, 18934, 18923, 18912, 18901, NA, NA, NA, NA, NA),
                 date = c("2020-01-01", "2020-02-01", "2020-03-01", 
                          "2020-04-01", "2020-05-01", "2020-06-01", 
                          "2020-07-01", "2020-08-01", "2020-09-01", 
                          "2020-10-01", "2020-11-01", "2020-12-01"))
df$date <- lubridate::as_date(df$date)

fit <- lm(pop ~ date, df)
na <- df[is.na(df$pop), "date", drop = FALSE]
newpop <- predict(fit, newdata = na)
na <- cbind(na, pop = newpop)
na
#>          date      pop
#> 8  2020-08-01 18889.45
#> 9  2020-09-01 18878.06
#> 10 2020-10-01 18867.03
#> 11 2020-11-01 18855.64
#> 12 2020-12-01 18844.61

plot(pop ~ date, df, ylim = c(18800, 19000), pch = 19)
points(pop ~ date, na, col = "red", pch = 19)
abline(fit)

创建于2022年12月20日,使用reprex v2.0.2

谢谢。我应该在我的问题中包含这个,但实际上我有许多年龄组和性别组合的相同数据。在实施此解决方案之前,我使用group_by对数据进行了分组,但是在生成的na数据框中,age_group和sex变量消失了。您知道我如何保留它们吗? - dd_data

0

如果您想使用approxExtrap()函数,xout是一个数字向量,其中包含您想要放置外推y值的x值。在您的情况下,它是date列的第8到12个值。

extrap_8to12 <- approxExtrap(df$date, df$pop, xout = df$date[8:12]) 
df$pop[8:12] <- extrap_8to12$y

df
# A tibble: 12 × 2
     pop date      
   <dbl> <date>    
 1 18968 2020-01-01
 2 18956 2020-02-01
 3 18946 2020-03-01
 4 18934 2020-04-01
 5 18923 2020-05-01
 6 18912 2020-06-01
 7 18901 2020-07-01
 8 18901 2020-08-01
 9 18901 2020-09-01
10 18901 2020-10-01
11 18901 2020-11-01
12 18901 2020-12-01

我尝试过这个,但所有外推值都等于最后一个非NA值。 - Rui Barradas
1
是的,没错。我在这里的唯一目的就是解释如何使用这个函数,因为 OP 说“不确定如何使用它,特别是对于 xout 要指定什么”。 - Abdur Rohman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接