วิธีคำนวณค่าเฉลี่ยถ่วงน้ำหนักใน 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สิ่งเดียวกันเพราะคุณจะพบเอกสารเพิ่มเติม
Lipis

1
ฟังก์ชั่นของคุณไม่ทำงาน แต่สิ่งนี้ใช้ได้กับฉัน: gist.github.com/totty90/b58f47dbc430a53d2e5b
Totty.js

1
มีอีกคำตอบที่ได้รับคะแนนสูงกว่าในหน้านี้ซึ่งใช้งานและใช้งานฟังก์ชั่นในตัวsumproduct
แบรดพาร์ค

58

หากน้ำหนักของคุณอยู่ในแถวที่ 2 จาก B ถึง L และข้อมูลที่คุณต้องการเฉลี่ยอยู่ในแถวที่ 3 ขึ้นไปให้บอกว่าคุณสามารถใช้ sumproduct ดังนี้:

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

7
+1 คำตอบนี้ง่ายใช้งานได้ดีกว่าคำตอบที่ยอมรับ
Waqar Lim

7

Google ดูเหมือนจะฟัง อย่างน้อยในอินสแตนซ์ของ Google ชีตของฉันฟังก์ชันนี้AVERAGE.WEIGHTEDมีอยู่ ตามความช่วยเหลือ:

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

ลิงค์ช่วยด้วย ไม่สามารถหาได้.
paragbaxi


2

รหัสของ Lipis ไม่ทำงานสำหรับฉันดังนั้นนี่คือการอัปเดต รหัสนี้:

  • ทำงานร่วมกับ Google Spreadsheets เวอร์ชันปัจจุบันได้อย่างถูกต้องที่อยู่องค์ประกอบของอาร์เรย์

  • ตรวจสอบว่าค่าเป็นตัวเลข

  • มีสวิตช์เพื่อพิจารณาค่าศูนย์หรือไม่

รหัส:

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

การแก้ไขโค้ดของ Lipis ให้ทำงานกับ Google Spreadsheets เวอร์ชันปัจจุบัน:

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!ผลลัพธ์ รหัส Lipis ที่ทำยังใช้งานได้ คุณไม่สนใจอาร์เรย์ 2d ที่ถูกส่งคืนเท่านั้น
Jacob Jan Tuinstra

0

ARRAYFORMULA () สามารถคำนวณค่าเฉลี่ยถ่วงน้ำหนักใน Google Spreadsheets (และอื่น ๆ )

การจัดเก็บน้ำหนักแยกกันใน 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))

NB regexp นั้นต้องการชื่อแอตทริบิวต์ที่ไม่มีตัวเลข ดังนั้นให้ใช้ 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 Spreadsheets?


0

เนื่องจากคำตอบที่ยอมรับคือการใช้ Google Apps Script ฉันจึงสร้างตัวอย่างข้อมูลเล็กน้อย

รหัส

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 Spreadsheets?


0

สำหรับค่าเฉลี่ยถ่วงน้ำหนักง่ายๆคุณสามารถเพิ่มมูลค่าของเซลล์ได้หลายครั้ง เช่นถ้าคุณต้องการให้ A1 เป็น 75% และ B1 เป็น 25% คุณสามารถใส่=AVERAGE (A1,A1,A1,B1)ได้ ดังนั้นสำหรับคุณโดยเฉพาะมันจะเป็น=AVERAGE (B2,C2,C2,D1,D2,D2,D2,D2,D2,D2)ซึ่งจะมีน้ำหนัก B2 เท่ากับครึ่งหนึ่งของ C2 (50%) และ D2 เป็น 3x C2 (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
Jacob Jan Tuinstra

@JacobJanTuinstra เหตุใดคำตอบนี้จึงปรากฏขึ้นเป็นอันดับแรกหากมีอันดับต่ำกว่าคำที่คุณอ้างอิง webapps stackexchange ทำงานได้ในรูปแบบที่ไม่แน่นอน ...
e18r
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.