我可以对特定数字使用 floor() 吗?

Can I use floor() to specific numbers?

我想floor()到下一个具体数字(不是数字,而是实际值)。 例如。年份列表:

valid_years = c(1990,2000,2006,2012,2018) # values to round to ("snap")

input  = c(1990, 1991, 1992, 1993, 2000, 2001, 2002, 2006, 2007, 2016, 2020)
output = c(1990, 1990, 1990, 1990, 2000, 2000, 2000, 2006, 2006, 2012, 2018)

以下输入的行为(或以上 ceil() 的情况下)指定值对我来说并不重要。在我的情况下,一个好的行为是捕捉到 valid_years 中的最低值,但这对我来说并不重要。

我知道我可以用 if-then-else(例如 if(x < 2006) x = 2000 else if(x < 2012) x = 2006 ...)实现这个,但我相信有更优雅的方法来解决这个问题。

我浏览了很多“R 中的舍入”问题,但尽管有许多措辞相似的问题,但都没有找到答案,这些问题都有其独特的(不同的)目标:例如, rounding to arbitrary number within a range or .

您可以使用 findInterval:

valid_years[findInterval(input, valid_years)]
#  [1] 1990 1990 1990 1990 2000 2000 2000 2006 2006 2012 2018
all(valid_years[findInterval(input, valid_years)] == output)
#  [1] TRUE

你可以

purrr::map_dbl(input, ~ tail(valid_years[valid_years <= .x], 1))

结果:

 [1] 1990 1990 1990 1990 2000 2000 2000 2006 2006 2012 2018

对于具有函数的基本 R 解决方案(希望我已经评论够了):

nearest <- function(samples, value) {
  # Return index of minimal absolute difference between samples and the value provided
  which.min(abs(samples - value))
}

round_to_values <- function(desired, input) {
  # Init the resulting vector to avoid growing within the loop
  results = input
  # Loop over the input values and fill result with the index of the nearest desired vector
  for (i in seq(1, length(input))) {
    results[i] = desired[nearest(desired, input[i])]
  }
  # return the results
  results
}

# Effectively call the function witht the inputs
valid_years = c(1990,2000,2006,2012,2018) # values to round to ("snap")
input  = c(1990, 1991, 1992, 1993, 2000, 2001, 2002, 2006, 2007, 2016, 2020)

round_to_values(valid_years, input)

结果是:

> round_to_values(valid_years, input)
 [1] 1990 1990 1990 1990 2000 2000 2000 2006 2006 2018 2018