วิธีแก้ไขข้อมูลในช่วงใน Google ชีต


9

ฉันมีอาเรย์กับข้อมูล:

   X      Y
   3     50
   5     60
   9    120
  11    130
  18     90
  20    150

ข้อมูลทั้งหมดไม่ใช่เชิงเส้น X รับประกันว่าจะถูกจัดเรียง

ทีนี้สำหรับค่าใดก็ตามที่ฉันต้องการให้มีการสอดแทรกเชิงเส้นระหว่างตัวเลข (เช่น 3 => 50, 4 => 55, 5 => 60) การแก้ไขแบบสองทางจะยิ่งดีกว่า แต่ฉันคาดหวังไว้ต่ำ

คำตอบ:


9

สคริปต์นี้จะทำเช่นเดียวกัน (บวกอีกเล็กน้อย)

รหัส

function myInterpolation(x, y, value) {
  if(value > Math.max.apply(Math, x) || value < Math.min.apply(Math, x)) {
    throw "value can't be interpolated !!";
    return;
  }

  var check = 0, index;
  for(var i = 0, iLen = x.length; i < iLen; i++) {
    if(x[i][0] == value) {
      return y[i][0];
    } else {      
      if(x[i][0] < value && ((x[i][0] - check) < (value - check))) {
        check = x[i][0];
        index = i;
      }
    }
  }

  var xValue, yValue, xDiff, yDiff, xInt;
  yValue = y[index][0];
  xDiff = x[index+1][0] - check;
  yDiff = y[index+1][0] - yValue;
  xInt = value - check; 

  return (xInt * (yDiff / xDiff)) + yValue;
}

อธิบาย

ในตอนต้นของสคริปต์มีข้อผิดพลาดเล็กน้อยในการจัดการ หลังจากนั้นมันจะค้นหารายการต่ำสุดครั้งแรกเมื่อเทียบกับค่าอินพุต เมื่อพบแล้วมันจะทำคณิตศาสตร์และนำเสนอผลลัพธ์

บันทึก

หากค่าที่เลือกเท่ากับ 20 สคริปต์ส่งกลับ 150 #DIV/0ที่อัตราผลตอบแทนสูตร

ภาพหน้าจอ

ป้อนคำอธิบายรูปภาพที่นี่

สูตร

ใช้สูตรต่อไปนี้เพื่อพิจารณาค่าทั้งหมด

=IF(
   ISNA(
     MATCH(C2,A2:A7,0)),
   FORECAST(
     $C$2,
     OFFSET(B$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1),
     OFFSET(A$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1)), 
   INDEX(
     B2:B7,
     MATCH(C2,A2:A7,0)
     ,0)
 )

 copy / paste
 =IF(ISNA(MATCH(C2, A2:A7, 0)), FORECAST($C$2,OFFSET(B$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1),OFFSET(A$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1)), INDEX(B2:B7, MATCH(C2, A2:A7, 0), 0))

ตัวอย่าง

เพิ่มสคริปต์ภายใต้เครื่องมือ> เครื่องมือแก้ไขสคริปต์และกดปุ่มบันทึก (ไม่จำเป็นต้องมีการตรวจสอบสิทธิ์)

ฉันได้สร้างไฟล์ตัวอย่างสำหรับคุณ: วิธีการแก้ไขข้อมูลในช่วงใน Google ชีต


2
ขอบคุณยาโคบ! พูดตามตรงฉันเกือบจะชอบเวอร์ชั่นของฉันดีกว่าเพราะมันใช้งานได้บนอุปกรณ์มือถือเช่นกัน (แอพ Android ชีตดั้งเดิมและเวอร์ชันมือถือของเว็บแอพไม่มีการสนับสนุนสคริปต์ที่น่าประทับใจ) แต่ฟังก์ชั่นของคุณสะอาดกว่า . ดังนั้นฉันจะเลือกคำตอบของคุณ
EboMike

@EboMike ฉันดูรหัสของฉันและสังเกตเห็นข้อผิดพลาด ฉันแก้ไขรหัสและมีสูตรเพื่อให้คุณสามารถใช้ในแอพมือถือของคุณ
Jacob Jan Tuinstra

2
และนี่คือเหตุผลว่าทำไมโชคไม่ดีที่คุณไม่สามารถตอบคำถามได้มากกว่าหนึ่งครั้ง :) ขอบคุณยาโคบ
EboMike

10

ฉันพบวิธีที่จะทำ - อาจมีวิธีที่ดีกว่า แต่นี่คือสิ่งที่ฉันคิดขึ้นมา:

สมมติว่าข้อมูลอยู่ใน A1: B10 และ $ C $ 1 มีคีย์เพื่อค้นหา:

=FORECAST($C$1,
    OFFSET(B$1,MATCH($C$1,A$1:A$10,1)-1,0,2,1),
    OFFSET(A$1,MATCH($C$1,A$1:A$10,1)-1,0,2,1))

ในรายละเอียด:

การคาดการณ์ทำการแก้ไขเชิงเส้น แต่จะถือว่าเป็นเส้นตรง ดังนั้นเราจำเป็นต้องค้นหาค่าสองค่าที่ล้อมรอบค่าที่เรากำลังมองหา

ดังนั้นเราใช้ MATCH เพื่อค้นหาหมายเลขแรกที่เท่ากับหรือสูงกว่าสิ่งที่เรากำลังมองหา

การคาดการณ์คาดว่าช่วงข้อมูลดังนั้นเราจึงใช้ OFFSET เพื่อสร้างการอ้างอิงไปยังช่วงข้อมูล MATCH นั้นได้รับการจัดทำดัชนีแล้วดังนั้นเราต้องลบมันก่อน เราสร้างช่วงที่กว้างหนึ่งและสองสูง ค่านี้รับประกันว่าจะใส่ $ C $ 1 ซึ่งเป็นค่าการค้นหาของเรา


+1; สูตรที่ดี !! เลือกจะส่งผลให้x=20 #DIV/0
Jacob Jan Tuinstra

1

นี่เป็นการดัดแปลงสคริปต์ของJacob Jan Tuinstraเพียงเล็กน้อยทำให้สามารถใช้อาร์เรย์หรือค่าเป็นอาร์กิวเมนต์ที่สามเพื่อให้ฟังก์ชันการแก้ไขสามารถคำนวณได้ในหลาย ๆ ที่พร้อมกัน ความแตกต่างเพียงอย่างเดียวคือเพิ่มบางบรรทัดที่จุดเริ่มต้น นี่เป็นวิธีที่รวดเร็วในการเปลี่ยนฟังก์ชั่นที่กำหนดเองให้เป็นฟังก์ชั่นที่กำหนดเองซึ่งยอมรับอาร์เรย์

function myInterpolation(x, y, value) {
  if (value.map) {
    return value.map(function(v) {
      return myInterpolation(x, y, v);
    });
  }
  //  the rest stays the same

  if (value > Math.max.apply(Math, x) || value < Math.min.apply(Math, x)) {
    throw "value can't be interpolated !!";
    return;
  }

  var check = 0, index;
  for(var i = 0, iLen = x.length; i < iLen; i++) {
    if(x[i][0] == value) {
      return y[i][0];
    } else {      
      if(x[i][0] < value && ((x[i][0] - check) < (value - check))) {
        check = x[i][0];
        index = i;
      }
    }
  }

  var xValue, yValue, xDiff, yDiff, xInt;
  yValue = y[index][0];
  xDiff = x[index+1][0] - check;
  yDiff = y[index+1][0] - yValue;
  xInt = value - check; 

  return (xInt * (yDiff / xDiff)) + yValue;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.