【问题标题】:Getting the two numbers on either side of the median获取中位数两侧的两个数字
【发布时间】:2016-01-05 07:31:15
【问题描述】:

给定:

x = [1.23, 2.0, 3.45, 4.1]

然后:

middle = numpy.median(x)

如果列表x 的大小为奇数,我可以使用x[x.index(middle)-1]x[x.index(middle)+1] 来获取中间两侧的两个数字。这在上述情况下不起作用,因为x 中不存在中位数。是否有可以处理偶数和奇数列表的标准方法?

【问题讨论】:

  • 刚刚意识到.index() 方法本身无论如何都会在奇数大小的列表中有相同条目时崩溃,因为它会错误地选择第一个出现。
  • 第一个大于中位数的元素和它之前的元素应该这样做,不是吗?
  • “第一个大于中位数的元素和紧接在它之前的元素”是目标本身:)
  • 呃,对不起。我没有看到你需要这种情况来处理均匀和不均匀的情况。
  • 也许您可以指定您的数组已排序?它大大简化了问题。

标签: python list python-2.7 numpy median


【解决方案1】:

假设排序后的输入列表的长度是N,那么在我看来,您想要访问元素N/2-1(N+1)/2(假设整数除法),即,

[1.23, 2.0, 3.45, 4.1] => N = 4 thus N/2-1 = 1 and (N+1)/2 = 2

[1.23, 2.0, 3.45, 4.1, 5.6] => N = 5 thus N/2-1 = 1 and (N+1)/2 = 3

【讨论】:

    【解决方案2】:

    这些是您正在寻找的numbers

    x[(len(x)-1)/2 - len(x)%2], x[len(x)/2 + len(x)%2]
    

    【讨论】:

    • 确实是我要找的号码,欧比旺。做得很好。
    【解决方案3】:

    要获得中位数,您必须有一个排序列表,所以这是一个简单的数学问题,如果列表长度不均匀,您需要 halfway point - 1halfway point + 1,如果列表长度是偶数 中位数是两个中间数字的平均值,所以你想要这两个中间数字。

    def get_two(l):
        ln = len(l)
        half = ln // 2
        return x[half-1], x[half + ln % 2]
    

    【讨论】:

      【解决方案4】:

      如果输入列表是未排序的(比如x = [1.23, 3.45, 4.1, 2.0]),那么您想要遍历并找到两个感兴趣的数量(当然这也适用于排序的输入)。像这样的:

      largestSmallerThanMedian = x[0]
      smallestLargerThanMedian = x[len(x)-1] 
      for n in x:
          if (n < middle) and (n >= largestSmallerThanMedian):
              largestSmallerThanMedian = n
          if (n > middle) and (n <= smallestLargerThanMedian):
              smallestLargerThanMedian = n
      

      然后largestSmallerThanMediansmallestLargerThanMedian 将有两个感兴趣的数量。

      【讨论】:

        【解决方案5】:

        根据定义,median 是将样本分成两半的值。

        一个有限的数字列表的中位数可以通过排列所有 从最低值到最高值的观察值并选择 中间一个(例如,{3, 3, 5, 9, 11} 的中位数是 5)。如果有一个 偶数个观测值,则不存在单个中间值;这 中位数通常被定义为两个中间值的平均值 ({3, 5, 7, 9} 的中位数为 (5 + 7) / 2 = 6)。

        所以,你需要

        • 以某种方式确定哪些样本是“下半部分”,哪些是“上半部分”,然后
        • 相应地从子集中选择最大值和最小值。

        可能的方法包括:

        • 对整个列表进行排序(为了提高效率可能就地排序),然后选择相应的元素。 (O(N*log(N)))
        • 遍历列表,将元素分类为“下”和“上”部分(实际上,您需要在每一步计算中值以对下一个元素进行分类)并跟踪您的“边界”值(无论如何你都需要它们来计算中位数)(O(N))

        所以,基本上,您需要的是(为您的一维案例更改链接源代码):

        if sz % 2 == 0:
            part = partition(a, ((sz // 2) - 1, sz // 2))
        else:
            part = partition(a, (sz - 1) // 2)
        

        然后检索相应的元素。

        但是,请注意,如果您追求效率,there's quite an overhead converting data into ndarray

        【讨论】:

          【解决方案6】:

          您可以使用bisect 模块:

          x = [1.23, 2.0, 3.45, 4.1]  
          
           def select_near_median(list_):
              # gets two numbers either side of median
              # in a sorted list
              # bisect finds the index where median number
              # can be inserted
              import bisect
              import statistics
              list_ = sorted(list_)
              med = statistics.median(list_)
              ind = bisect.bisect_left(list_, med)
              if med == list_[ind]:
                  left = ind
                  right = left + 1
              else:
                  left = ind - 1
                  right = ind
              return list_[left], list_[right]
          
          
                  print(select_near_median([1,2,3,4]))
                  (2, 3)
                  print(select_near_median([1,2,3,4,5]))
                  (3, 4)
                  print(select_near_med(x))
                  (2.0, 3.45)
          

          【讨论】:

          • 但语句med(list_) 计算的是算术平均值,而不是中位数,不是吗?
          • @LetzerWille 谢谢。但是对于[1,2,3,4] 之类的列表,它会返回(1,2)
          • @LetzerWille 我们快到了……它现在正在为一个奇数大小的列表做类似的事情,例如select_near_median([1,2,3,4,5])(2,3)。注意:由于我使用的是 2.7,因此我不得不将 statistics.median 替换为`numpy.median,但我认为这没有什么区别。
          • @Pyderman 现在应该可以工作了。 bisect 函数是违反直觉的,但具有持久性:)
          • @Pyderman bisect 适用于排序输入。所以我已经完成了这个 llPrices = sorted ([..... 并且输出了 783.765。实际上我已经写了关于排序输入的内容。更好的是我会将排序放入函数中。
          猜你喜欢
          • 2018-09-15
          • 1970-01-01
          • 1970-01-01
          • 2011-07-20
          • 1970-01-01
          • 2012-09-11
          • 2017-12-16
          • 2016-06-11
          • 1970-01-01
          相关资源
          最近更新 更多