Як обчислити середньозважені середні показники в Google Таблицях?


36

У мене є Google Таблиці, де продукти вказані у вигляді рядків, а атрибути - як стовпці. Атрибут кожного продукту оцінюється за шкалою 1-10. Мій останній стовпець - це середнє значення цих значень (тобто =Average(B2:D2)). Це добре працює, якщо кожен атрибут має однакову вагу.

+--------+-------+-------+-------+---------+
|        | Attr1 | Attr2 | Attr3 | Overall |
+--------+-------+-------+-------+---------+
| Prod 1 | 10    | 8     | 9     | 9       |
| Prod 2 | 2     | 10    | 7     | 6.33    |
| Prod 3 | 4     | 6     | 6     | 5.33    |
+--------+-------+-------+-------+---------+

Проблема полягає в тому, що я хочу, щоб кожен атрибут мав різну вагу. Наприклад, Attr1 може не бути важливим і повинен коштувати лише 50%, тоді як Attr3 дуже важливий і повинен становити 300%.

+--------+-------------+-------+--------------+---------+
|        | Attr1 (50%) | Attr2 | Attr3 (300%) | Overall |
+--------+-------------+-------+--------------+---------+
| Prod 1 | 10          | 8     | 9            | 8.89    |
| Prod 2 | 2           | 10    | 7            | 7.11    |
| Prod 3 | 4           | 6     | 6            | 5.78    |
+--------+-------------+-------+--------------+---------+

Значення для першого ряду було б:

(10*0.5 + 8*1 + 9*3) / (0.5+1+3) = 8.89

які можна обчислити, використовуючи:

(
  B2*(IFERROR(REGEXEXTRACT(B1, "\d+"), 100)/100) 
  + C2*(IFERROR(REGEXEXTRACT(C1, "\d+"), 100)/100)
  + D2*(IFERROR(REGEXEXTRACT(D1, "\d+"), 100)/100) 
) / (
  IFERROR(REGEXEXTRACT(B1, "\d+"), 100)/100
  + IFERROR(REGEXEXTRACT(C1, "\d+"), 100)/100
  + IFERROR(REGEXEXTRACT(D1, "\d+"), 100)/100
)

що, як бачите, може стати дуже важким для управління, оскільки додаються більше атрибутів. В ідеалі я шукаю рішення, яке не потребує створення тимчасових комірок, щоб допомогти з розрахунками.

Чи є якась вбудована функція чи загальна умова, яка може допомогти мені обчислити ці середньозважені середні показники?

Відповіді:


8

Немає вбудованої функції для обчислення середньозваженого значення, тому вам потрібно написати спеціальну функцію, якщо ви хочете уникати використання занадто багато тимчасових комірок. Тож ось як можна досягти своєї мети.

Перейдіть до Інструменти > Сценарії > Редактор сценаріїв ... , Скопіюйте / Вставте наступний код і збережіть його:

function weightedAverage(v, w) {
  var sum_v = 0;
  var sum_w = 0;

  if (v[0].length != w[0].length) {
    return "#ERROR: Incorrect number of values and weights";  
  }

  for (var c = 0; c < v[0].length; ++c) {
    sum_v += v[0][c] * w[0][c]; 
    sum_w += w[0][c]; 
  }

  return sum_v/sum_w;
}​

Використовуйте його так:

=weightedAverage(B3:D3,$B$2:$D$2) 

Де B3:D3ваші цінності та $B$2:$D$2ваги. Це не підтвердження помилок (єдина перевірка - переконатися, що обидва масиви мають однакову довжину), але це зробить трюк.

У наведеному вище прикладі я не намагаюся витягнути ваги з назви атрибута, але читаю їх з другого ряду ( B2:D2), щоб зробити наше життя простішим і зрозумілішим. $Не міняє результат формули. Це впливає лише на те, що відбувається, коли ви копіюєте формулу в іншу клітинку. Частина посилання на комірку, що слідує за $, не зміниться ( посилання для отримання більш детальної інформації). Запишіть формулу один раз у комірку E3і скопіюйте її в інші рядки, щоб побачити її в дії.


Що означають $знаки?
Розсудливий

@Senseful Я оновив свою відповідь, і ви можете взагалі Google, оскільки dollar sign in excelце те саме, оскільки ви знайдете більше документації на неї.
Ліпіс

1
Ваша функція не працює. Але це працює для мене: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js

1
На цій сторінці є ще одна відповідь з більш високим рейтингом, яка працює і використовує вбудовану функціюsumproduct
Brad Parks

58

Якщо ваги знаходяться у другому рядку від B до L, а дані, які ви хочете в середньому, є у рядках 3 та вище, скажімо, тоді ви можете використовувати підсумок таким чином:

=sumproduct(B$2:L$2, C3:L3)/sum(B$2:L$2)

7
+1 ця відповідь проста, робоча і набагато краща за прийняту.
Afr


2

Код Ліпіса для мене не працює, тому ось оновлення. Цей код:

  • працює з поточною версією електронних таблиць Google, правильно коректуючи елементи масиву

  • перевіряє, чи є значення числами

  • має перемикач для врахування нульових значень чи ні

Код:

/**
  v - Values range
  w - Weights range
  z - count zero values?
*/

function weightedAverage(v, w, z) {
  var sum_v = 0;
  var sum_w = 0;

  if (v.length != w.length) {
    return "#ERROR: Incorrect number of values and weights";  
  }

  for (var c = 0; c < v.length; ++c) {
    if (!z && Number(v[c][0])!=0) {
      sum_v += Number(v[c][0]) * Number(w[c][0]); 
      sum_w += Number(w[c][0]); 
    }
  }

  return sum_v/sum_w;
}

0

Виправлення коду Ліпіса для роботи з поточною версією електронних таблиць Google:

function weightedAverage(v, w) {
  var sum_v = 0;
  var sum_w = 0;

  if (v.length != w.length) {
    return "#ERROR: Incorrect number of values and weights";  
  }

  for (var c = 0; c < v.length; ++c) {
    sum_v += v[c] * w[c]; 
    sum_w += w[c] * 1; 
  }

  return sum_v/sum_w;
}​

-1; Я перевірив ваш код у нових таблицях Google, і він не спрацював, і #NUM!в результаті вийшов. Код, зроблений Ліпісом, все ще працює. Ви ігноруєте лише повернення 2d-масиву, який повертається.
Яків Ян Туінстра

0

ARRAYFORMULA () може обчислити середньозважений показник в електронних таблицях Google (і більше).

Зберігання ваг окремо у B2: D2 спрощує читання формули. Обчислення середньозваженого для E3 потім виглядає аналогічно SUMPRODUCT () вище (копіювати / вставляти для E4 & E5):

=ARRAYFORMULA(sum(B3:D3 * $B$2:$D$2)/sum($B$2:$D$2))

+--------+-------------+-------+-------------+---------+
|        | AttrA (50%) | AttrB | AttrC (300%)| Overall |
| Weight:|        50%  |  100% |        300% |         |
+--------+-------------+-------+-------------+---------+
| Prod 1 |       10    |  8    |       9     | 8.8889  |
| Prod 2 |        2    | 10    |       7     | 7.1111  |
| Prod 3 |        4    |  6    |       6     | 5.7778  |
+--------+-------------+-------+-------------+---------+

Використання RegExExtract () для отримання ваг від $ B $ 1: $ D $ 1 - це проста зміна в ARRAYFORMULA (). Замініть простий діапазон більш складним виразом " iferror(regexextract($B$1:$D$1,"\d+"),100)/100" і формула для E3 стає (скопіювати / вставити для E4 і E5):

=ARRAYFORMULA(sum(B3:D3 * iferror(regexextract($B$1:$D$1,"\d+"),100)/100)/sum(iferror(regexextract($B$1:$D$1,"\d+"),100)/100))

Примітка. Для регулярного вираження потрібні імена атрибутів без чисел; тому використовуйте AttrA, AttrB & AttrC замість Attr1, Attr2 & Attr3.


0

Уважно прочитавши своє запитання,

В ідеалі я шукаю рішення, яке не потребує створення тимчасових комірок, щоб допомогти з розрахунками.

Я придумав таке рішення, яке не використовує тимчасових комірок.

Формула

weights = ARRAYFORMULA(IFERROR(VALUE(REGEXEXTRACT($B$1:$D$1,"\((\d+)")),100))

=SUMPRODUCT(B3:D3, weights) / SUM(weights)

copy / paste
=SUMPRODUCT(B2:D2, ARRAYFORMULA(IFERROR(VALUE(REGEXEXTRACT($B$1:$D$1,"\((\d+)")),100)))/SUM(ARRAYFORMULA(IFERROR(VALUE(REGEXEXTRACT($B$1:$D$1,"\((\d+)")),100)))

Знімок екрана

введіть тут опис зображення

Пояснив

REGEXEXTRACTВитягне значення в заголовку після першої прямої дужки та VALUEперетворює його в число. IFERRORВстановить значення в , 100якщо нічого не знайдено , і ARRAYFORMULAдозволить вибрати діапазон, а не окремих клітин.

Приклад

Я створив для вас прикладний файл: як обчислити середньозважені середні таблиці в електронних таблицях Google?


0

Оскільки прийнята відповідь використовує сценарій Google Apps, я також створив невеликий фрагмент.

Код

function weightedAverage(v, w) {
  var weights = [], sumWeights = 0;
  for(var k = 0, kLen = w[0].length; k < kLen; k++) {
    var m = w[0][k].match(/\((\d+)/), value;
    if(!m) {
      value = 100;
    } else {
      value = Number(m[1]);
    }
    weights.push(value);
    sumWeights += value;
  }

  var output = [];
  for(var i = 0, iLen = v.length; i < iLen; i++) {
    var sumProduct = 0;
    for(var j = 0, jLen = v[0].length; j < jLen; j++) {
      sumProduct += v[i][j] * weights[j]; 
    }
    output.push(sumProduct / sumWeights);
  } 
  return output;
}

Знімок екрана

введіть тут опис зображення

Примітка

Сценарій буде дотримуватися тієї ж логіки, що і в цій публікації. Основна перевага полягає в тому, що вона підрахує загальні значення одразу.

Приклад

Я створив для вас прикладний файл: як обчислити середньозважені середні таблиці в електронних таблицях Google?


0

Для простих середньозважених середніх значень можна просто додати значення комірки кілька разів. Начебто, якщо ви хочете, щоб A1 становив 75%, а B1 - 25%, можете ввести =AVERAGE (A1,A1,A1,B1). Отже, конкретно для вашого, це було б =AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2), яке важило б В2 як половину С2 (50%), а Д2 - 3х С2 (300%).

Складніші речі вище моєї категорії оплати. :)


0

Насправді обидві версії Average.weighted та sumproduct дають однаковий результат:

AVERAGE.WEIGHTED("Values","Weight")

SUMPRODUCT("Numbers","Weight")/sum("Weight")

Тому я скоріше використовую перший, оскільки це набагато простіше впоратися, але я не знаю, як додати до цієї формули інші ваги.

Це підказка, але не знаю, як додати лише ваги, а не додаткові значення

AVERAGE.WEIGHTED(values, weights, [additional_values, ...], [additional_weights, ...])

Це трохи розпливчасто. Ви намагаєтесь задати нове запитання чи це відповідь?
jonsca

-2

Існує досить простий спосіб використання лише заданих функцій.

=(sumproduct(E5:E9;G5:G9)/sum(E5:E9))   

де вміст E - кількість балів, а G - значення цих балів.


2
Цю відповідь уже було дано: webapps.stackexchange.com/a/29919/29140
Яків Ян

@JacobJanTuinstra Чому ця відповідь відображається спочатку, якщо вона оцінена набагато нижчою за ту, яку ви посилаєте? webapps stackexchange працює загадковими способами ...
e18r
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.