Обновление: В свете дополнительной информации из комментариев, это будет делать то, что хочет ОП:
foobar <- function(x, mid, y) {
## x, input data on range 0,1
## mid, midpoint X in OP's Q
## y, % of points around mid
sx <- sort(x)
want <- sx >= mid
## what do you want to do if y% of x is not integer?
num <- floor(((y/100) * length(x)) / 2)
high <- if((len <- length(want[want])) == 0) {
1
} else {
if(len < num) {
tail(sx, 1)
} else {
sx[want][num]
}
}
low <- if((len <- length(want[!want])) == 0) {
0
} else {
if(len < num) {
head(sx, 1)
} else {
rev(sx[!want])[num]
}
}
res <- c(low, high)
names(res) <- c("low","high")
res
}
Что дает следующее на выборке случайных значений на интервале0,1:
> set.seed(1)
> x <- runif(20)
> sort(x)
[1] 0.06178627 0.17655675 0.20168193 0.20597457 0.26550866 0.37212390
[7] 0.38003518 0.38410372 0.49769924 0.57285336 0.62911404 0.66079779
[13] 0.68702285 0.71761851 0.76984142 0.77744522 0.89838968 0.90820779
[19] 0.94467527 0.99190609
> foobar(x, 0.4, 20)
low high
0.3800352 0.5728534
ОП ответила на вопросы ниже, и версия функции выше делает, как было запрошено, и в свете комментариев.
ТамЕсть несколько вопросов для решения:
- Что вы хотите сделать, если
y
% данных не является целым числом? На данный момент, если y
% данных оценивается как 4.2
Я округляю до floor(4.2)
, но мы можем округлить до ceiling(4.2)
. - Что вы хотите сделать, если выше 0 значенийили ниже выбранной средней точки? В настоящий момент код возвращает указанные экстремумы (0,1) в этих случаях.
- Что вы хотите сделать, если есть некоторые значения выше /ниже средней точки, но недостаточно в заданном направлении, чтобы охватить
y/2
% в каком-либо одном направлении? В настоящий момент я возвращаюон крайние точки данных, которые лежат выше / ниже средней точки.Это немного противоречит предыдущему пункту, должны ли мы возвращать крайние значения 0, 1 и в этом случае?
Оригинал: Это даст вам то, что выхотите, предполагая, что вы предполагаете предположения (равномерно распределенные по диапазону 0,1)
foo <- function(x, y) {
## x is the mid-point
## y is the % range about x, i.e. y/2 either side of x
x + (c(-1,1) * (((y/100) / 2) * 1))
}
> foo(0.4, 20)
[1] 0.3 0.5
Мы могли бы расширить функцию, чтобы разрешить произвольный диапазон со значениями по умолчанию 0, 1:
bar <- function(x, y, min = 0, max = 1) {
## x is the mid-point
## y is the % range about x, i.e. y/2 either side of x
## min, max, the lower and upper bounds on the data
stopifnot(x >= min & x <= max)
x + (c(-1,1) * (((y/100) / 2) * (max - min)))
}
> bar(0.4, 20)
[1] 0.3 0.5
> bar(0.6, 20, 0.5, 1)
[1] 0.55 0.65
> bar(0.4, 20, 0.5, 1)
Error: x >= min & x <= max is not TRUE