¿Cómo calcular los promedios ponderados en las Hojas de cálculo de Google?


36

Tengo un Google Sheets donde los productos se enumeran como filas y los atributos como columnas. El atributo de cada producto se clasifica en una escala de 1-10. Mi última columna es un promedio de estos valores (es decir =Average(B2:D2)). Esto funciona bien si cada atributo tiene el mismo 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    |
+--------+-------+-------+-------+---------+

El problema es que quiero que cada atributo tenga un peso diferente. Por ejemplo, Attr1 podría no ser importante y solo debería valer el 50%, mientras que Attr3 es muy importante y debería valer el 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    |
+--------+-------------+-------+--------------+---------+

El valor para la primera fila sería:

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

que podría calcularse usando:

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

que, como puede ver, puede ser muy difícil de administrar a medida que se agregan más atributos. Idealmente, estoy buscando una solución que no requiera la creación de celdas temporales para ayudar con los cálculos.

¿Existe alguna función incorporada o una convención común que pueda ayudarme a calcular estos promedios ponderados?

Respuestas:


8

No hay una función integrada para calcular el promedio ponderado, por lo que debe escribir una función personalizada si desea evitar el uso de demasiadas celdas temporales. Así es como puedes lograr tu objetivo.

Vaya a Herramientas > Scripts > Editor de scripts ... , copie / pegue el siguiente código y guárdelo:

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

Úselo como:

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

¿Dónde B3:D3están tus valores y $B$2:$D$2tus pesos? No es a prueba de errores (la única comprobación es asegurarse de que ambas matrices tengan la misma longitud), pero funcionará.

En el ejemplo anterior, no estoy tratando de extraer los pesos del título del atributo, pero los estoy leyendo desde la segunda fila ( B2:D2) para hacer nuestra vida más fácil y más clara. El $no está cambiando el resultado de la fórmula. Solo afecta lo que sucede cuando estás copiando la fórmula en otra celda. La parte de la referencia de celda después de $ no cambiará ( enlace para más detalles). Escriba la fórmula una vez en la celda E3y cópiela al resto de las filas para verla en acción.


¿Qué $significan los signos?
Sentido

@Senseful Actualicé mi respuesta, y puedes buscar en Google en general porque dollar sign in exceles lo mismo, ya que encontrarás más documentación al respecto.
Lipis

1
Tu función no funciona. Pero esto funciona para mí: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js

1
Hay otra respuesta mejor calificada en esta página que funciona y utiliza la función integradasumproduct
Brad Parks,

58

Si sus pesos están en la fila 2 de B a L, y los datos que desea promediar están en las filas 3 y más altas, por ejemplo, puede usar sumproduct de la siguiente manera:

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

77
+1 esta respuesta es simple, funciona y es mucho mejor que la aceptada.
Afr


2

El código de Lipis no funcionaba para mí, así que aquí hay una actualización. Este código:

  • funciona con la versión actual de las hojas de cálculo de Google que abordan correctamente los elementos de la matriz

  • comprueba si los valores son números

  • tiene un interruptor para considerar valores cero o no

Código:

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

Corregir el código de Lipis para que funcione con la versión actual de las hojas de cálculo de 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; Probé su código en las nuevas Hojas de cálculo de Google y no funcionó, #NUM!como resultado. El código que Lipis hizo todavía funciona. Solo está ignorando la matriz 2d que se devuelve.
Jacob Jan Tuinstra

0

ARRAYFORMULA () puede calcular un promedio ponderado en las hojas de cálculo de Google (y más).

Almacenar los pesos por separado en B2: D2 simplifica la lectura de la fórmula. Calcular el promedio ponderado para E3 es similar a SUMPRODUCT () anterior (copiar / pegar para E4 y 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  |
+--------+-------------+-------+-------------+---------+

Usar RegExExtract () para obtener los pesos de $ B $ 1: $ D $ 1 es un cambio simple en ARRAYFORMULA (). Reemplace el rango simple con la expresión más compleja " iferror(regexextract($B$1:$D$1,"\d+"),100)/100" y la fórmula para E3 se convierte en (copiar / pegar para E4 y E5):

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

Nota: Regexp requiere nombres de atributos sin números; entonces, use AttrA, AttrB y AttrC en lugar de Attr1, Attr2 y Attr3.


0

Habiendo leído tu pregunta cuidadosamente,

Idealmente, estoy buscando una solución que no requiera la creación de celdas temporales para ayudar con los cálculos.

Se me ocurrió esta solución, que no usa celdas temporales.

Fórmula

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

Captura de pantalla

ingrese la descripción de la imagen aquí

Explicado

El REGEXEXTRACTextraerá el valor en la cabecera después de la primera abrazadera recta y VALUElo convertirá en un número. La IFERRORfijará el valor en 100si no se encuentra nada y ARRAYFORMULAhará que sea posible seleccionar un rango, en lugar de las células individuales.

Ejemplo

He creado un archivo de ejemplo para usted: ¿Cómo calcular los promedios ponderados en las hojas de cálculo de Google?


0

Como la respuesta aceptada es usar Google Apps Script, también creé un pequeño fragmento.

Código

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

Captura de pantalla

ingrese la descripción de la imagen aquí

Nota

El guión seguirá la misma lógica que se presenta en esta publicación. La principal ventaja es que calculará los valores generales de una vez.

Ejemplo

He creado un archivo de ejemplo para usted: ¿Cómo calcular los promedios ponderados en las hojas de cálculo de Google?


0

Para promedios ponderados simples , puede agregar el valor de la celda varias veces. Como si desea que A1 sea 75% y B1 25%, puede ingresar =AVERAGE (A1,A1,A1,B1). Entonces, específicamente para el suyo, sería =AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2), lo que pesaría B2 como la mitad de C2 (50%) y D2 como 3x C2 (300%).

Las cosas más complicadas están por encima de mi calificación salarial. :)


0

En realidad, ambas versiones Average.weighted y sumproduct dan el mismo resultado:

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

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

Así que prefiero usar el primero ya que es mucho más simple de manejar, sin embargo, no sé cómo agregar otros pesos a esta fórmula.

Esta es la información sobre herramientas, pero no sé cómo agregar solo pesos y no valores adicionales

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

Esto es un poco vago. ¿Estás tratando de hacer una nueva pregunta o es una respuesta?
jonsca

-2

Hay una manera bastante simple de usar solo funciones dadas.

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

donde E contenido es el número de puntos y G la importancia de esos puntos.



@JacobJanTuinstra ¿Por qué esta respuesta aparece primero si tiene una calificación mucho más baja que la que está haciendo referencia? webapps stackexchange funciona de manera misteriosa ...
e18r
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.