Come calcolare le medie ponderate in Fogli Google?


36

Ho un Fogli Google in cui i prodotti sono elencati come righe e gli attributi come colonne. L'attributo di ogni prodotto è valutato su una scala da 1 a 10. La mia ultima colonna è una media di questi valori (cioè =Average(B2:D2)). Funziona bene se ogni attributo ha lo stesso peso.

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

Il problema è che voglio che ogni attributo abbia un peso diverso. Ad esempio, Attr1 potrebbe non essere importante e dovrebbe valere solo il 50%, mentre Attr3 è molto importante e dovrebbe valere il 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    |
+--------+-------------+-------+--------------+---------+

Il valore per la prima riga sarebbe:

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

che potrebbe essere calcolato utilizzando:

(
  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
)

che, come puoi vedere, può diventare molto difficile da gestire con l'aggiunta di più attributi. Idealmente, sto cercando una soluzione che non richiede la creazione di celle temporanee per aiutare con i calcoli.

Esiste una funzione integrata o una convenzione comune che può aiutarmi a calcolare queste medie ponderate?

Risposte:


8

Non esiste una funzione integrata per calcolare la media ponderata, quindi è necessario scrivere una funzione personalizzata se si desidera evitare di utilizzare troppe celle temporanee. Ecco quindi come puoi raggiungere il tuo obiettivo.

Vai su Strumenti > Script > Editor di script ... , Copia / Incolla il codice seguente e salvalo:

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;
}​

Usalo come:

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

Dove B3:D3sono i tuoi valori e i $B$2:$D$2tuoi pesi. Non è a prova di errore (l'unico controllo è assicurarsi che entrambi gli array abbiano la stessa lunghezza) ma farà il trucco.

Nell'esempio sopra non sto cercando di estrarre i pesi dal titolo dell'attributo, ma li sto leggendo dalla seconda riga ( B2:D2) per rendere la nostra vita più semplice e chiara. Non $sta cambiando il risultato della formula. Influisce solo su ciò che accade quando si copia la formula in un'altra cella. La parte del riferimento di cella che segue $ non cambierà ( link per maggiori dettagli). Scrivi la formula una volta nella cella E3e copiala nel resto delle righe per vederla in azione.


Cosa significano i $segni?
Senso

@Senseful Ho aggiornato la mia risposta, e in generale puoi Google per dollar sign in excella stessa cosa poiché troverai più documentazione per essa.
Lipis,

1
La tua funzione non funziona. Ma questo funziona per me: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js

1
C'è un'altra risposta più votata in questa pagina che funziona e usa la funzione integratasumproduct
Brad Parks,

58

Se i tuoi pesi sono nella riga 2 da B a L e i dati che vuoi mediare sono nelle righe 3 e successive, ad esempio, puoi utilizzare il sottoprodotto come segue:

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

7
+1 questa risposta è semplice, funzionante e molto migliore di quella accettata.
Afr


2

Il codice di Lipis non funzionava per me, quindi ecco un aggiornamento. Questo codice:

  • funziona con la versione corrente di Fogli di lavoro Google indirizzando correttamente gli elementi dell'array

  • controlla se i valori sono numeri

  • ha un interruttore per considerare o meno i valori zero

Codice:

/**
  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

Correggere il codice di Lipis in modo che funzioni con la versione corrente di Fogli di lavoro 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; Ho testato il tuo codice nei nuovi Fogli Google e non ha funzionato, #NUM!come risultato. Il codice fatto da Lipis funziona ancora. Stai solo ignorando l'array 2d che viene restituito.
Jacob Jan Tuinstra,

0

ARRAYFORMULA () può calcolare una media ponderata in Fogli di lavoro Google (e altro).

Memorizzare i pesi separatamente in B2: D2 semplifica la lettura della formula. Il calcolo della media ponderata per E3 appare quindi simile a SUMPRODUCT () sopra (copia / incolla per E4 ed 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  |
+--------+-------------+-------+-------------+---------+

L'uso di RegExExtract () per ottenere i pesi da $ B $ 1: $ D $ 1 è una semplice modifica di ARRAYFORMULA (). Sostituisci l'intervallo semplice con l'espressione " iferror(regexextract($B$1:$D$1,"\d+"),100)/100" più complessa e la formula per E3 diventa (copia / incolla per E4 ed E5):

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

NB Che regexp richiede nomi di attributi senza numeri; quindi, utilizzare AttrA, AttrB e AttrC invece di Attr1, Attr2 e Attr3.


0

Dopo aver letto attentamente la tua domanda,

Idealmente, sto cercando una soluzione che non richiede la creazione di celle temporanee per aiutare con i calcoli.

Ho trovato questa soluzione, che non utilizza celle temporanee.

Formula

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)))

Immagine dello schermo

inserisci qui la descrizione dell'immagine

spiegato

Il REGEXEXTRACTestrarrà il valore nell'intestazione dopo la prima staffa diritta e VALUEconvertirà in un numero. Il IFERRORimposterà il valore in 100se nulla viene trovato e la ARRAYFORMULArenderà possibile selezionare un intervallo, piuttosto che singole cellule.

Esempio

Ho creato un file di esempio per te: come calcolare le medie ponderate nei fogli di calcolo di Google?


0

Poiché la risposta accettata utilizza Google Apps Script, ho anche creato un piccolo frammento.

Codice

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;
}

Immagine dello schermo

inserisci qui la descrizione dell'immagine

Nota

Lo script seguirà la stessa logica presentata in questo post. Il vantaggio principale è che calcolerà i valori complessivi contemporaneamente.

Esempio

Ho creato un file di esempio per te: come calcolare le medie ponderate nei fogli di calcolo di Google?


0

Per medie ponderate semplici , puoi semplicemente aggiungere il valore della cella più volte. Ad esempio, se desideri che A1 sia 75% e B1 25%, puoi inserire =AVERAGE (A1,A1,A1,B1). Quindi, in particolare per il tuo, sarebbe =AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2), che peserebbe B2 come metà di C2 (50%) e D2 come 3x C2 (300%).

Le cose più complicate sono al di sopra del mio voto. :)


0

In realtà entrambe le versioni con peso medio e sottoprodotto danno lo stesso risultato:

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

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

Quindi preferisco usare il primo poiché è molto più semplice gestirlo, tuttavia non so come aggiungere altri pesi a questa formula.

Questa è la descrizione comando, ma non so come aggiungere solo pesi e non valori aggiuntivi

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

Questo è un po 'vago. Stai cercando di porre una nuova domanda o questa è una risposta?
jonsca

-2

C'è un modo abbastanza semplice usando solo determinate funzioni.

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

dove E contenuto è il numero di punti e G l'importanza di quei punti.


2
Quella risposta era già stata data: webapps.stackexchange.com/a/29919/29140
Jacob Jan Tuinstra,

@JacobJanTuinstra Perché questa risposta viene visualizzata per prima se è classificata in modo molto inferiore a quella a cui ti riferisci? webapps stackexchange funziona in modo misterioso ...
e18r
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.