Взвешивание любого набора чисел для суммирования до нуля в R

#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