计算中位数 - JavaScript

57

我一直在尝试计算中位数,但似乎存在一些数学问题,因为我无法得到正确的中位数值,也无法弄清原因。这是代码;

class StatsCollector {

    constructor() {
        this.inputNumber = 0;
        this.average = 0;

        this.timeout = 19000;

        this.frequencies = new Map();
        for (let i of Array(this.timeout).keys()) {
            this.frequencies.set(i, 0);
        }
    }

    pushValue(responseTimeMs) {
        let req = responseTimeMs;
        if (req > this.timeout) {
            req = this.timeout;
        }

        this.average = (this.average * this.inputNumber + req) / (this.inputNumber + 1);

        console.log(responseTimeMs / 1000)
        let groupIndex = Math.floor(responseTimeMs / 1000);
        this.frequencies.set(groupIndex, this.frequencies.get(groupIndex) + 1);

        this.inputNumber += 1;
    }

    getMedian() {
        let medianElement = 0;
        if (this.inputNumber <= 0) {
            return 0;
        }
        if (this.inputNumber == 1) {
            return this.average
        }
        if (this.inputNumber == 2) {
            return this.average
        }
        if (this.inputNumber > 2) {
            medianElement = this.inputNumber / 2;
        }

        let minCumulativeFreq = 0;
        let maxCumulativeFreq = 0;
        let cumulativeFreq = 0;
        let freqGroup = 0;
        for (let i of Array(20).keys()) {
            if (medianElement <= cumulativeFreq + this.frequencies.get(i)) {
                minCumulativeFreq = cumulativeFreq;
                maxCumulativeFreq = cumulativeFreq + this.frequencies.get(i);
                freqGroup = i;
                break;
            }
            cumulativeFreq += this.frequencies.get(i);
        }

        return (((medianElement - minCumulativeFreq) / (maxCumulativeFreq - minCumulativeFreq)) + (freqGroup)) * 1000;
    }

    getAverage() {
        return this.average;
    }

}

当我输入以下数值时,以下是结果的快照:

342、654、987、1093、2234、6243、7087、20123

enter image description here

正确的结果应该是:

中位数:1663.5


也许可以在这里查看如何在 JavaScript 中从数组中找到中位数(8个或9个值)。 - Radek Hofman
3
计算中位数需要对值进行排序,并选择中间的值。 - Pointy
2
那不是中位数。中位数应该在集合中。 - jmargolisvt
我的第一个猜测是你有一个四舍五入误差。 - victor
1
中位数是排序后列表的中间数字,如果值的数量为奇数,则中位数就是该数字。如果值的数量为偶数,则中位数是中间两个值的中点或平均值。 - Mark B
1
可能是[在JavaScript中从数组中查找中位数值(8个值或9个值)]的重复问题(https://dev59.com/UYLba4cB1Zd3GeqPfHtU)。 - str
17个回答

0

更简单、更高效

const median = dataSet => {
  if (dataSet.length === 1) return dataSet[0]
  const sorted = ([ ...dataSet ]).sort()
  const ceil = Math.ceil(sorted.length / 2)
  const floor = Math.floor(sorted.length / 2)
  if (ceil === floor) return sorted[floor]
  return ((sorted[ceil] + sorted[floor]) / 2)
}

0
为了在时间复杂度方面获得更好的性能,请使用最大堆 - 最小堆来查找数组流的中位数。

0

function Median(arr){
    let len = arr.length;
    arr = arr.sort();
    let result = 0;
    let mid = Math.floor(len/2);
    if(len % 2 !== 0){
        result += arr[mid];
    }
    if(len % 2 === 0){
        result += (arr[mid] + arr[mid+1])/2
    }
    return result;
    
}

console.log(`The median is ${Median([0,1,2,3,4,5,6])}`)


0

更简单、更高效、易于阅读

  1. 克隆数据以避免对原始数据进行修改。
  2. 对值列表进行排序。
  3. 获取中间点。
  4. 从列表中获取中位数。
  5. 返回中位数。

function getMedian(data) {
    const values = [...data];
    const v   = values.sort( (a, b) => a - b);
    const mid = Math.floor( v.length / 2);
    const median = (v.length % 2 !== 0) ? v[mid] : (v[mid - 1] + v[mid]) / 2; 
    return median;
}


1
虽然您的回答可能解决了问题,但是包括解释如何以及为什么解决问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。您可以编辑您的答案以添加解释,并指出适用的限制和假设。- 来自审核 - Adam Marshall
1
你写了“更简单和更高效”,但是很好知道你在与什么进行比较,因为许多人已经用类似的代码回答了。本质上,“sort”操作决定了执行时间,大多数答案都使用了它。 - trincot
无法工作 console.log(getMedian([-0.51182868190794402, 0.33955843791573237, 1.073205764212215])); - DavidDunham

0

简单解决方案:

function calcMedian(array) {
  const {
    length
  } = array;

  if (length < 1)
    return 0;

  //sort array asc
  array.sort((a, b) => a - b);

  if (length % 2) {
    //length of array is odd
    return array[(length + 1) / 2 - 1];
  } else {
    //length of array is even
    return 0.5 * [(array[length / 2 - 1] + array[length / 2])];
  }
}

console.log(2, calcMedian([1, 2, 2, 5, 6]));
console.log(3.5, calcMedian([1, 2, 2, 5, 6, 7]));
console.log(9, calcMedian([13, 9, 8, 15, 7]));
console.log(3.5, calcMedian([1, 4, 6, 3]));
console.log(5, calcMedian([5, 1, 11, 2, 8]));


0

       const medianArr = (x) => {
        let sortedx = x.sort((a,b)=> a-b);
        let halfIndex = Math.floor(sortedx.length/2);
        
         return (sortedx.length%2) ? (sortedx[Math.floor(sortedx.length/2)]) :  ((sortedx[halfIndex-1]+sortedx[halfIndex])/2)
    }
    
    console.log(medianArr([1,2,3,4,5]));
    console.log(medianArr([1,2,3,4,5,6]));


-1

function findMedian(arr) {
  arr.sort((a, b) => a - b)

  let i = Math.floor(arr.length / 2)
  return arr[i]
}

let result = findMedian([0, 1, 2, 4, 6, 5, 3])
console.log(result)


1
你的答案有问题,请修正它。请添加解释,仅有代码的答案可能会被审核标记为低质量。 - Jan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接