Làm cách nào để tính trung bình có trọng số trong Google Sheets?


36

Tôi có Google Sheets nơi các sản phẩm được liệt kê dưới dạng hàng và thuộc tính dưới dạng cột. Mỗi thuộc tính của sản phẩm được đánh giá theo thang điểm từ 1-10. Cột cuối cùng của tôi là trung bình của các giá trị này (tức là =Average(B2:D2)). Điều này hoạt động tốt nếu mỗi thuộc tính có cùng trọng lượng.

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

Vấn đề là tôi muốn mỗi thuộc tính có trọng lượng khác nhau. Ví dụ: Attr1 có thể không quan trọng và chỉ nên có giá trị 50%, trong khi Attr3 rất quan trọng và nên có giá trị 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    |
+--------+-------------+-------+--------------+---------+

Giá trị cho hàng đầu tiên sẽ là:

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

có thể được tính bằng cách sử dụng:

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

mà, như bạn có thể thấy, có thể trở nên rất khó quản lý khi thêm nhiều thuộc tính. Lý tưởng nhất là tôi đang tìm một giải pháp không yêu cầu tạo các ô tạm thời để giúp tính toán.

Có bất kỳ chức năng được xây dựng hoặc một quy ước chung nào có thể giúp tôi tính các trung bình có trọng số này không?

Câu trả lời:


8

Không có hàm tích hợp để tính trung bình có trọng số, do đó bạn phải viết một hàm tùy chỉnh nếu bạn muốn tránh sử dụng quá nhiều ô tạm thời. Vì vậy, đây là cách bạn có thể đạt được mục tiêu của mình.

Chuyển đến Công cụ > Tập lệnh > Trình chỉnh sửa tập lệnh ... , Sao chép / Dán mã dưới đây và lưu nó:

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

Sử dụng nó như:

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

Đâu B3:D3là giá trị và $B$2:$D$2trọng lượng của bạn. Đây không phải là bằng chứng lỗi (kiểm tra duy nhất là đảm bảo cả hai mảng có cùng độ dài) nhưng nó sẽ thực hiện thủ thuật.

Trong ví dụ trên tôi không cố trích xuất các trọng số từ tiêu đề của thuộc tính, nhưng tôi đang đọc chúng từ hàng thứ hai ( B2:D2) để làm cho cuộc sống của chúng ta dễ dàng và rõ ràng hơn. Các $không thay đổi kết quả của công thức. Nó chỉ ảnh hưởng đến những gì đang xảy ra khi bạn sao chép công thức trong một ô khác. Phần tham chiếu ô theo $ sẽ không thay đổi ( liên kết để biết thêm chi tiết). Viết công thức một lần trong ô E3và Sao chép nó vào phần còn lại của các hàng để xem nó hoạt động.


Những $dấu hiệu có ý nghĩa gì?
Nhận thức

@Senseful Tôi đã cập nhật câu trả lời của mình và bạn có thể nói chung Google cho dollar sign in excelđiều tương tự vì bạn sẽ tìm thấy nhiều tài liệu hơn cho nó.
Lipis

1
Chức năng của bạn không hoạt động. Nhưng điều này hiệu quả với tôi: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js

1
Có một câu trả lời được đánh giá cao hơn trên trang này hoạt động và sử dụng chức năng tích hợp sẵnsumproduct
Brad park

58

Nếu trọng số của bạn nằm ở hàng 2 từ B đến L và dữ liệu bạn muốn trung bình nằm ở hàng 3 trở lên, thì bạn có thể sử dụng sumproduct như sau:

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

7
+1 câu trả lời này đơn giản, hiệu quả và tốt hơn nhiều so với câu trả lời được chấp nhận.
Afr


2

Mã của Lipis không hoạt động với tôi, vì vậy đây là bản cập nhật. Mã này:

  • hoạt động với phiên bản hiện tại của Bảng tính Google giải quyết chính xác các yếu tố mảng

  • kiểm tra xem các giá trị có phải là số không

  • có chuyển đổi để xem xét giá trị 0 hay không

Mã số:

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

Sửa mã của Lipis để hoạt động cho phiên bản Bảng tính Google hiện tại:

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; Tôi đã kiểm tra mã của bạn trong Google Sheets mới và nó không hoạt động, #NUM!kết quả là nó đã cho kết quả. Mã Lipis thực hiện vẫn hoạt động. Bạn chỉ bỏ qua mảng 2d đang được trả về.
Jacob Jan Tuinstra

0

ARRAYFORMULA () có thể tính trung bình có trọng số trong Bảng tính Google (và hơn thế nữa).

Lưu trữ các trọng số riêng biệt trong B2: D2 đơn giản hóa việc đọc công thức. Tính trung bình có trọng số cho E3 sau đó trông tương tự như SUMPRODVEL () ở trên (sao chép / dán cho 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  |
+--------+-------------+-------+-------------+---------+

Sử dụng RegExExtract () để có trọng số từ $ B $ 1: $ D $ 1 là một thay đổi đơn giản trong ARRAYFORMULA (). Thay thế phạm vi đơn giản bằng biểu thức phức tạp hơn " iferror(regexextract($B$1:$D$1,"\d+"),100)/100" và công thức cho E3 trở thành (sao chép / dán cho 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 Điều đó regrec yêu cầu tên thuộc tính không có số; vì vậy, sử dụng AttrA, AttrB & AttrC thay vì Attr1, Attr2 & Attr3.


0

Đọc kỹ câu hỏi của bạn

Lý tưởng nhất là tôi đang tìm một giải pháp không yêu cầu tạo các ô tạm thời để giúp tính toán.

Tôi đã đưa ra giải pháp này, sử dụng không có tế bào tạm thời.

Công thức

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

Ảnh chụp màn hình

nhập mô tả hình ảnh ở đây

Giải thích

Các REGEXEXTRACTsẽ trích xuất các giá trị trong tiêu đề sau khung thẳng đầu tiên và VALUEsẽ chuyển đổi nó thành một số. Ý IFERRORchí sẽ đặt giá trị tại 100nếu không tìm thấy gì và ARRAYFORMULAsẽ cho phép chọn một phạm vi, thay vì các ô riêng lẻ.

Thí dụ

Tôi đã tạo một tệp ví dụ cho bạn: Cách tính trung bình có trọng số trong Bảng tính Google?


0

Vì câu trả lời được chấp nhận đang sử dụng Google Apps Script, tôi cũng đã tạo một đoạn nhỏ.

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

Ảnh chụp màn hình

nhập mô tả hình ảnh ở đây

chú thích

Kịch bản sẽ tuân theo logic tương tự như được trình bày trong bài viết này . Ưu điểm chính là nó sẽ tính toán các giá trị tổng thể cùng một lúc.

Thí dụ

Tôi đã tạo một tệp ví dụ cho bạn: Cách tính trung bình có trọng số trong Bảng tính Google?


0

Đối với mức trung bình có trọng số đơn giản , bạn chỉ cần thêm giá trị ô nhiều lần. Giống như nếu bạn muốn A1 là 75% và B1 là 25%, bạn có thể đặt vào =AVERAGE (A1,A1,A1,B1). Vì vậy, cụ thể đối với bạn, nó sẽ có =AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2)trọng lượng B2 bằng một nửa so với C2 (50%) và D2 ​​là 3x C2 (300%).

Những thứ phức tạp hơn là trên mức lương của tôi. :)


0

Trên thực tế cả hai phiên bản Average. weighted và sumproduct đều cho kết quả như nhau:

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

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

Vì vậy, tôi thay vì sử dụng cách đầu tiên đơn giản hơn để xử lý nó, tuy nhiên tôi không biết cách thêm các trọng số khác vào công thức này.

Đây là chú giải công cụ, nhưng không biết cách chỉ thêm trọng lượng và không thêm giá trị

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

Điều này hơi mơ hồ. Bạn đang cố gắng hỏi một câu hỏi mới hay đây là một câu trả lời?
jonsca

-2

Có một cách khá đơn giản chỉ sử dụng các chức năng nhất định.

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

Trong đó nội dung E là số điểm và G tầm quan trọng của những điểm đó.


2
Câu trả lời đó đã được đưa ra: webapps.stackexchange.com/a/29919/29140
Jacob Jan Tuinstra

@JacobJanTuinstra Tại sao câu trả lời này hiển thị đầu tiên nếu nó được đánh giá thấp hơn so với câu bạn đang tham khảo? webapps stackexchange hoạt động theo những cách khác nhau ...
e18r
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.