这看似微不足道,但我有一个代码可以找到一组三个数字中最接近的两个数字的平均值。所以有5个例子:
x1 <- c(1,5,7)
x2 <- c(NA,2,3)
x3 <- c(2,6,4)
x4 <- c(1,NA,NA)
x5 <- c(1,3,1)
我会得到
的输出y1 = 6
y2 = 2.5
y3 = 4
y4 = 1
y5 = 1
分别。基本上,找到最接近的2个数字,然后对它们求平均值,考虑NA和关系。
此代码是一个怪物:
x <-x[!is.na(x)]
x <-x[order(x)]
y <-ifelse(length(x) == 1, x,
ifelse(length(x) == 2, mean(x),
ifelse(length(x) == 3,
ifelse(abs(x[1] - x[2]) == abs(x[2] - x[3]), mean(x),
ifelse(abs(x[1] - x[2]) > abs(x[2] - x[3]), mean(x[2:3]),
ifelse(abs(x[1] - x[2]) < abs(x[2] - x[3]), mean(x[1:2]),
"error"))), NA)))
它有效,但因为这是一个较大的for
循环的一部分,我想知道有更好的方法来做这件事。
答案 0 :(得分:4)
我们使用"list"
和"default"
方法定义S3泛型。
"default"
方法采用向量并对其进行排序(也删除NA值),然后如果剩下的长度为&lt; = 1,则返回单个值,否则返回NA。如果长度为2或两个连续差异相同则返回所有值的平均值;否则,它找到最接近的两个值对中的第一个的索引,并返回值的平均值。
"list"
方法重复应用默认方法。
mean_min_diff <- function(x) UseMethod("mean_min_diff")
mean_min_diff.list <- function(x) sapply(x, mean_min_diff.default)
mean_min_diff.default <- function(x) {
x0 <- sort(x)
if (length(x0) <= 1) c(x0, NA)[1]
else if (length(x0) == 2 || sd(diff(x0)) == 0) mean(x0)
else mean(x0[seq(which.min(diff(x0)), length = 2)])
}
现在测试一下:
mean_min_diff(x1)
## [1] 6
mean_min_diff(list(x1, x2, x3, x4, x5))
## [1] 6.0 2.5 4.0 1.0 1.0