#r #sum #weighted-average
#r #сумма #средневзвешенное
Вопрос:
Я хочу написать функцию в R, которая вычисляет веса для суммирования любого набора чисел в R до нуля. Например, если
x <- c(-5, 6, 2, 4, -3)
Я хочу функцию, которая возвращала бы новый вектор, который был взвешен, чтобы принудительно свести векторную сумму к нулю, снимая что-то с положительных чисел и добавляя что-то к отрицательным значениям…
РЕДАКТИРОВАТЬ: чтобы уточнить, я не хочу сдвигать значения вверх или вниз по шкале… Я хочу взвесить так, чтобы масштабируемые отрицательные числа стали немного более / менее отрицательными, а масштабируемые положительные числа стали немного менее / более положительными.
Я не уверен 1) как вычислить правильные значения для пропорциональных весов и 2) есть ли функция в R, которая может это сделать?
Комментарии:
1. Используйте
x - mean(x)
Ответ №1:
Как насчет
x <- scale(x)
> x
[,1]
[1,] -1.2450825
[2,] 1.1162809
[3,] 0.2576033
[4,] 0.6869421
[5,] -0.8157437
attr(,"scaled:center")
[1] 0.8
attr(,"scaled:scale")
[1] 4.658326
> sum(scale(x))
[1] 5.551115e-17
Редактировать:
Как было предложено @Josh O’brien, установка scale = FALSE дает
scale(x, scale = FALSE)
[,1]
[1,] -5.8
[2,] 5.2
[3,] 1.2
[4,] 3.2
[5,] -3.8
attr(,"scaled:center")
[1] 0.8
sum(scale(x, scale = FALSE))
[1] 6.661338e-16
Комментарии:
1. Вероятно, вам следует установить
scale(x, scale=FALSE)
так, чтобы он просто центрировался (и также не нормализовал значения по их (центрированному) стандартному отклонению).
Ответ №2:
1) смещения @jdharrison уже указал, что если вы хотите, чтобы вектор a
sum(x-a)
был равен нулю, то установка a
значения среднего значения x
сделает это.
2) вектор веса В формулировке вопроса, похоже, задается вектор веса w
, такой, что sum(w * x)
равен нулю.
(i) Если x
не является постоянным (т.Е. Его элементы не все одинаковы), то в математической записи P = I-xx'/(x'x)
— это проекция, ортогональная x
и P1 = 1 - xx'1/(x'x
) — вектор в диапазоне P
so, переключающийся на R-код:
w <- 1 - x * sum(x) / sum(x*x)
является таким вектором веса. Мы можем проверить это:
> sum(w*x)
[1] 2.220446e-16
(ii) Если x
является постоянным, но не тождественно нулевым, тогда выберите любой непостоянный вектор s <- seq_along(x)
, скажем. Тогда Ps = s - xx's/(x'x)
ортогонально x
so:
x <- c(1, 1, 1, 1)
s <- seq_along(x)
w <- s - x * sum(s*x) / sum(x*x)
sum(w * x)
предоставление:
> sum(w * x)
[1] 0
Комментарии:
1. Спасибо.. вторая часть с весами была тем, что я искал…. работает с нулями
![]()
2. @g-grothendieck просто поиграл с этим снова… получите какое-то неожиданное поведение с большим числом … например, x <- c(-5, -3, 0, 2, 4, 6, 20); rescale_zero <- функция(x){ w <- 1 — x * сумма (x) / сумма (x x); w x };rescale_zero(x) … 20 масштабируется до 0,4081 (меньше, чем другие пять чисел?)
3. Результирующее значение w ортогонально x, и это все, что требуется.
Ответ №3:
Уточнение комментария @jdharrison:
> x
[1] -5 6 2 4 -3
> sum(x)
[1] 4
> mean(x)
[1] 0.8
> x - mean(x)
[1] -5.8 5.2 1.2 3.2 -3.8
> sum(x - mean(x))
[1] 6.661338e-16 #floating point 0
Так x - mean(x)
будет делать трюк.
Ответ №4:
Если вы хотите сохранить знак после масштабирования…
x <- c(-5, -3, 0, 2, 4, 6, 50)
rescale_zero <- function(x){
x1 <- x[x>0]
x2 <- x[x<0]
d <- (sum(x1) sum(x2)) / 2
w1 <- (sum(x1) - d) / sum(x1)
w2 <- (sum(x2) - d) / sum(x2)
y <- x
y[x>0] <- x1*w1
y[x<0] <- x2*w2
y
}
rescale_zero(x)
# [1] -21.875000 -13.125000 0.000000 1.129032 2.258065 3.387097 28.225806