我有一个包含日期列表的数据框。我还有一个向量形式的参考日期列表。我创建了一个可复制的数据框和向量。除了创建日期框之外,您可以忽略“r”对象。
i=500;j=500;n=50
r <- do.call(stack, replicate(n,raster(matrix(runif(i*j), i, j))))
( dates <- seq(as.Date("2020/10/23"), by = 16, length.out = 20) )
s <- as(sampleRandom(r[[1]], 100, sp=TRUE), "sf")
df <- as.data.frame(s)
df$date <- sample(dates, nrow(s), replace=TRUE)
我想找到每个数据框行中距离最近的向量日期最近的日期。然后在数据框中的新列中返回最接近的向量日期。
作为参考,我将使用它来将矢量日期与栅格堆栈中的相应栅格进行匹配,并根据日期进行提取。这就是为什么 's' 最初是 'sf' 类型,而我也有 'r' 对象。
要实现这一点,您必须决定是否寻找 过去、未来或两者的最近日期。如果您选择两者,则需要 决定如果两个日期距离相同该怎么办。
这里有两种方法。
left_join()
并在 closest()
中使用 join_by()
。# Boiled down example of what you describe in your question.
library(tidyverse)
dates <- seq(as.Date("2020/10/23"),
by = 16,
length.out = 20)
dates2 <- sample(dates, 10)
df <- tibble(date = sample(dates, 30, replace = TRUE))
closest()
和 join_by()
这会寻找一个方向上最接近的日期。
ref_df <-
tibble(date_vector = dates2)
left_join(df, ref_df,
by = join_by(closest(date <= date_vector)),
keep = TRUE)
#> # A tibble: 30 × 2
#> date date_vector
#> <date> <date>
#> 1 2020-12-26 2020-12-26
#> 2 2020-10-23 2020-11-08
#> 3 2021-07-22 2021-08-23
#> 4 2021-03-16 2021-03-16
#> 5 2021-04-17 2021-05-03
#> 6 2021-04-17 2021-05-03
#> 7 2021-04-17 2021-05-03
#> 8 2021-04-17 2021-05-03
#> 9 2021-01-11 2021-03-16
#> 10 2020-12-26 2020-12-26
#> # ℹ 20 more rows
如果我们想从两个方向看,我们可以这样做:
left_join(df, ref_df,
by = join_by(closest(date <= date_vector)),
keep = TRUE) |>
left_join(ref_df,
by = join_by(closest(date >= date_vector)),
keep = TRUE) |>
# Reverse the order of date_vector.x and date_vector.y in the
# coalesce() call to decide which direction to prefer.
mutate(closest_date = coalesce(date_vector.x, date_vector.y))
#> # A tibble: 30 × 4
#> date date_vector.x date_vector.y closest_date
#> <date> <date> <date> <date>
#> 1 2020-12-26 2020-12-26 2020-12-26 2020-12-26
#> 2 2020-10-23 2020-11-08 NA 2020-11-08
#> 3 2021-07-22 2021-08-23 2021-07-06 2021-08-23
#> 4 2021-03-16 2021-03-16 2021-03-16 2021-03-16
#> 5 2021-04-17 2021-05-03 2021-03-16 2021-05-03
#> 6 2021-04-17 2021-05-03 2021-03-16 2021-05-03
#> 7 2021-04-17 2021-05-03 2021-03-16 2021-05-03
#> 8 2021-04-17 2021-05-03 2021-03-16 2021-05-03
#> 9 2021-01-11 2021-03-16 2020-12-26 2021-03-16
#> 10 2020-12-26 2020-12-26 2020-12-26 2020-12-26
#> # ℹ 20 more rows
自定义函数看起来是双向的。
# Function that finds the closest date in a vector of dates.
find_closest_date <- function(date, date_vector)
{
date_vector <- unique(date_vector)
diffs <- abs(date - date_vector)
# Two dates in date_vector can have the same distance to date, by adding
# `[1]` we pick whichever comes first in date_vector.
date_vector[diffs == min(diffs)][1]
}
# Test the function for one date.
find_closest_date(dates[1], dates2)
#> [1] "2020-11-08"
# Apply function to all dates.
df |>
mutate(closest_date = map(date, find_closest_date, dates2) |>
list_simplify())
#> # A tibble: 30 × 2
#> date closest_date
#> <date> <date>
#> 1 2020-12-26 2020-12-26
#> 2 2020-10-23 2020-11-08
#> 3 2021-07-22 2021-07-06
#> 4 2021-03-16 2021-03-16
#> 5 2021-04-17 2021-05-03
#> 6 2021-04-17 2021-05-03
#> 7 2021-04-17 2021-05-03
#> 8 2021-04-17 2021-05-03
#> 9 2021-01-11 2020-12-26
#> 10 2020-12-26 2020-12-26
#> # ℹ 20 more rows