Bagaimana cara menghitung rata-rata tertimbang di Google Sheets?

36

Saya memiliki Google Sheets di mana produk terdaftar sebagai baris dan atribut sebagai kolom. Atribut setiap produk dinilai pada skala 1-10. Kolom terakhir saya adalah rata-rata dari nilai-nilai ini (yaitu =Average(B2:D2)). Ini berfungsi dengan baik jika setiap atribut memiliki bobot yang sama.

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

Masalahnya adalah saya ingin setiap atribut memiliki bobot yang berbeda. Misalnya, Attr1 mungkin tidak penting dan seharusnya hanya bernilai 50%, sedangkan Attr3 sangat penting dan harus bernilai 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    |
+--------+-------------+-------+--------------+---------+

Nilai untuk baris pertama adalah:

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

yang dapat dihitung dengan menggunakan:

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

yang, seperti yang Anda lihat, dapat menjadi sangat sulit untuk dikelola karena lebih banyak atribut ditambahkan. Idealnya, saya mencari solusi yang tidak memerlukan pembuatan sel sementara untuk membantu perhitungan.

Apakah ada fungsi bawaan atau konvensi umum yang dapat membantu saya menghitung rata-rata tertimbang ini?

Masuk akal
sumber

Jawaban:

8

Tidak ada fungsi bawaan untuk menghitung rata-rata tertimbang sehingga Anda harus menulis fungsi khusus jika Anda ingin menghindari menggunakan terlalu banyak sel sementara. Jadi di sini adalah bagaimana Anda dapat mencapai tujuan Anda.

Buka Alat > Skrip > Editor skrip ... , Salin / Tempel kode di bawah ini dan simpan:

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

Gunakan seperti:

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

Di mana B3:D3nilai dan $B$2:$D$2bobot Anda? Itu bukan bukti kesalahan (satu-satunya pemeriksaan adalah untuk memastikan kedua array memiliki panjang yang sama) tetapi itu akan melakukan trik.

Dalam contoh di atas saya tidak mencoba untuk mengekstraksi bobot dari judul atribut, tetapi saya membacanya dari baris kedua ( B2:D2) untuk membuat hidup kita lebih mudah dan lebih jelas. Tidak $mengubah hasil rumus. Ini hanya memengaruhi apa yang terjadi ketika Anda menyalin rumus di sel lain. Bagian dari referensi sel setelah $ tidak akan berubah ( tautan untuk detail lebih lanjut). Tulis formula sekali dalam sel E3dan Salin ke seluruh baris untuk melihatnya beraksi.

Lipis
sumber
Apa $artinya tanda - tanda itu?
Senseful
@Senseful Saya memperbarui jawaban saya, dan Anda dapat Google secara umum untuk dollar sign in excelitu adalah hal yang sama karena Anda akan menemukan lebih banyak dokumentasi untuk itu.
Lipis
1
Fungsi Anda tidak berfungsi. Tetapi ini berhasil bagi saya: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js
1
Ada jawaban yang berperingkat lebih tinggi pada halaman ini yang berfungsi dan menggunakan fungsi sumproduct
bawaan
58

Jika bobot Anda berada di baris 2 dari B ke L, dan data yang ingin Anda rata-rata berada di baris 3 dan lebih tinggi, katakanlah, maka Anda dapat menggunakan sumproduct sebagai berikut:

=sumproduct(B$2:L$2, C3:L3)/sum(B$2:L$2)
Brendan Murphy
sumber
7
+1 jawaban ini sederhana, berfungsi, dan jauh lebih baik daripada yang diterima.
Afr
7

Google sepertinya telah mendengarkan. Setidaknya dalam contoh Google Sheets saya, fungsinya AVERAGE.WEIGHTEDada. Per bantuan:

=AVERAGE.WEIGHTED(values,
                  weights,
                  [additional_values, ...],
                  [additional_weights, ...])
Tony Shouse
sumber
Tautan untuk membantu. Tidak bisa menemukan.
paragbaxi
2

Kode Lipis tidak berfungsi untuk saya, jadi inilah pembaruan. Kode ini:

  • bekerja dengan versi Google Spreadsheets yang saat ini menangani elemen array dengan benar

  • memeriksa apakah nilainya adalah angka

  • memiliki saklar untuk mempertimbangkan nilai nol atau tidak

Kode:

/**
  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;
}
Zhenya Morozov
sumber
0

Memperbaiki kode Lipis agar berfungsi untuk versi Google Spreadsheets saat ini:

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;
}​
Sai
sumber
-1; Saya menguji kode Anda di Google Sheets baru dan itu tidak berhasil, itu memberi #NUM!hasilnya. Kode yang dibuat Lipis masih berfungsi. Anda hanya mengabaikan array 2d yang dikembalikan.
Jacob Jan Tuinstra
0

ARRAYFORMULA () dapat menghitung rata-rata tertimbang di Google Spreadsheets (dan banyak lagi).

Menyimpan bobot secara terpisah di B2: D2 menyederhanakan membaca rumus. Menghitung rata-rata tertimbang untuk E3 kemudian terlihat mirip dengan SUMPRODUCT () di atas (salin / tempel untuk 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  |
+--------+-------------+-------+-------------+---------+

Menggunakan RegExExtract () untuk mendapatkan bobot dari $ B $ 1: $ D $ 1 adalah perubahan sederhana di ARRAYFORMULA (). Ganti kisaran sederhana dengan " iferror(regexextract($B$1:$D$1,"\d+"),100)/100" ekspresi yang lebih kompleks dan menjadi rumus untuk E3 (copy / paste untuk 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))

NB Regexp itu memerlukan nama atribut tanpa angka; jadi, gunakan AttrA, AttrB & AttrC bukan Attr1, Attr2 & Attr3.

MW
sumber
0

Setelah membaca pertanyaan Anda dengan cermat,

Idealnya, saya mencari solusi yang tidak memerlukan pembuatan sel sementara untuk membantu perhitungan.

Saya datang dengan solusi ini, yang tidak menggunakan sel sementara.

Rumus

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

Tangkapan layar

masukkan deskripsi gambar di sini

Dijelaskan

The REGEXEXTRACTakan mengekstrak nilai dalam header setelah braket lurus pertama dan VALUEakan mengubahnya menjadi sebuah angka. The IFERRORakan menetapkan nilai pada 100jika tidak ada yang ditemukan dan ARRAYFORMULAakan memungkinkan untuk memilih berbagai, daripada sel-sel individual.

Contoh

Saya telah membuat contoh file untuk Anda: Bagaimana cara menghitung rata-rata tertimbang di Google Spreadsheets?

Jacob Jan Tuinstra
sumber
0

Karena jawaban yang diterima menggunakan Skrip Google Apps, saya juga membuat cuplikan kecil.

Kode

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

Tangkapan layar

masukkan deskripsi gambar di sini

Catatan

Script akan mengikuti logika yang sama seperti yang disajikan dalam posting ini . Keuntungan utama adalah bahwa ia akan menghitung nilai keseluruhan sekaligus.

Contoh

Saya telah membuat contoh file untuk Anda: Bagaimana cara menghitung rata-rata tertimbang di Google Spreadsheets?

Jacob Jan Tuinstra
sumber
0

Untuk rata-rata tertimbang sederhana , Anda bisa menambahkan nilai sel beberapa kali. Seperti jika Anda ingin A1 menjadi 75% dan B1 menjadi 25%, Anda dapat memasukkan =AVERAGE (A1,A1,A1,B1). Jadi khusus untuk Anda, itu akan menjadi =AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2), yang akan menimbang B2 sebagai setengah dari C2 (50%) dan D2 sebagai 3x C2 (300%).

Hal-hal yang lebih rumit berada di atas nilai gaji saya. :)

Jason
sumber
0

Sebenarnya kedua versi Average.weighted dan sumproduct memberikan hasil yang sama:

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

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

Jadi saya lebih suka menggunakan yang pertama karena cara ini lebih mudah untuk menanganinya, namun saya tidak tahu bagaimana menambahkan bobot lain ke formula ini.

Ini adalah tooltip, tetapi tidak tahu bagaimana cara menambahkan hanya bobot dan bukan nilai tambahan

AVERAGE.WEIGHTED(values, weights, [additional_values, ...], [additional_weights, ...])
Joao Carpio
sumber
Ini agak kabur. Apakah Anda mencoba mengajukan pertanyaan baru atau ini jawaban?
jonsca
-2

Ada cara yang cukup sederhana dengan hanya menggunakan fungsi yang diberikan.

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

di mana konten E adalah jumlah poin dan G pentingnya poin-poin tersebut.

Adam
sumber
2
Jawaban yang sudah diberikan: webapps.stackexchange.com/a/29919/29140
Jacob Jan Tuinstra
@JacobJanTuinstra Mengapa jawaban ini muncul lebih dulu jika dinilai jauh lebih rendah daripada yang Anda rujuk? webapps stackexchange berfungsi dengan cara misterius ...
e18r