【问题标题】:Python: categorising a list by orders of magnitudePython:按数量级对列表进行分类
【发布时间】:2013-05-30 14:44:56
【问题描述】:

我有一个包含值的嵌套列表:

list = [
...
['Country1', 142.8576737907048, 207.69725105029553, 21.613192419863577, 15.129178465784218],
['Country2', 109.33326343550823, 155.6847323746669, 15.450489646386226, 14.131554442715336],
['Country3', 99.23033109735835, 115.37122637190915, 5.380298424850267, 5.422030104456135],
...]

我想按数量级计算第二个索引/列中的值,从最低数量级开始,到最大数量级结束......例如

99.23033109735835 = 10 <= x < 100
142.8576737907048 = 100 <= x < 1000
             9432 = 1000 <= x < 10000

目的是输出一个简单的字符 (#) 计数,用于表示每个类别中有多少索引值,例如

  10 <= x < 100: ###
100 <= x < 1000: #########

我首先获取索引的 max() 和 min() 值,以便自动计算最大和最小量级类别,但我不确定如何将列中的每个值与顺序相关联量级...如果有人能指出我正确的方向或给我一些想法,我将不胜感激。

【问题讨论】:

  • 您希望看到的值的范围是多少?

标签: python


【解决方案1】:

这个函数会将你的 double 变成一个整数数量级:

>>> def magnitude(x):
...     return int(math.log10(x))
... 
>>> magnitude(99.23)
1
>>> magnitude(9432)
3

(所以10 ** magnitude(x) &lt;= x &lt;= 10 ** (1 + magnitude(x)) 代表所有x)。

只需将幅度用作键,并计算每个键的出现次数。 defaultdict 在这里可能会有所帮助。


请注意,此大小仅适用于 10 的正幂(因为int(double) 截断舍入为零)。

使用

def magnitude(x):
    return int(math.floor(math.log10(x)))

如果这对您的用例很重要。 (感谢 larsmans 指出这一点)。

【讨论】:

  • magnitude(6) == magnitude(.3) 使用此定义。这似乎不对。
  • 是的,我没有考虑负数
  • int(floor(log10(x))) 完成这项工作。
  • 我打算把它留给你的答案,但既然你已经删除了它,我会在这里编辑它以确保完整性......
  • 我实际上会采用 math.ceil()。
【解决方案2】:

将Useless'答案扩展到所有实数,你可以使用:

import math

def magnitude (value):
    if (value == 0): return 0
    return int(math.floor(math.log10(abs(value))))

测试用例:

In [123]: magnitude(0)
Out[123]: 0

In [124]: magnitude(0.1)
Out[124]: -1

In [125]: magnitude(0.02)
Out[125]: -2

In [126]: magnitude(150)
Out[126]: 2

In [127]: magnitude(-5280)
Out[127]: 3

【讨论】:

    【解决方案3】:

    如果x 是您的号码之一,那么len(str(int(x))) 是什么?

    或者,如果你有小于 0 的数字,int(math.log10(x)) 是什么?

    (另请参阅 log10 的文档。另请注意,此处的 int() 舍入可能不是您想要的 - 请参阅 ceil 和 floor,并注意您可能需要 int(ceil(...)) 或 int(floor(...))得到一个整数答案)

    【讨论】:

    • 在math 框外的想法很好,但不要把你的答案写成问题;相反,也许提供实际结果
    【解决方案4】:

    按数量级分类:

    from math import floor, log10
    from collections import Counter
    counter =  Counter(int(floor(log10(x[1]))) for x in list)
    

    1 是从 10 到小于 100,2 从 100 到小于 1000。

    print counter
    Counter({2: 2, 1: 1})
    

    然后它只是简单地打印出来

    for x in sorted(counter.keys()):
        print "%d <= x < %d: %d" % (10**x, 10**(x+1), counter[x])
    

    【讨论】:

      【解决方案5】:

      如果您想要重叠范围或具有任意边界的范围(不坚持数量级/2 的幂/任何其他可预测的系列):

      from collections import defaultdict
      lst = [
          ['Country1', 142.8576737907048, 207.69725105029553, 21.613192419863577, 15.129178465784218],
          ['Country2', 109.33326343550823, 155.6847323746669, 15.450489646386226, 14.131554442715336],
          ['Country3', 99.23033109735835, 115.37122637190915, 5.380298424850267, 5.422030104456135],
      ]
      
      buckets = {
          '10<=x<100': lambda x: 10<=x<100,
          '100<=x<1000': lambda x: 100<=x<1000,
      }
      
      result = defaultdict(int)
      for item in lst:
          second_column = item[1]
          for label, range_check in buckets.items():
              if range_check(second_column):
                  result[label] +=1
      
      print (result)
      

      【讨论】:

        【解决方案6】:

        另一个选项,使用bisect

        import bisect
        from collections import Counter
        list0 = [
        ['Country1', 142.8576737907048, 207.69725105029553, 21.613192419863577, 15.129178465784218],
        ['Country2', 109.33326343550823, 155.6847323746669, 15.450489646386226, 14.131554442715336],
        ['Country3', 99.23033109735835, 115.37122637190915, 5.380298424850267, 5.422030104456135]
        ]
        
        magnitudes = [10**x for x in xrange(5)]
        c = Counter(bisect.bisect(magnitudes, x[1]) for x in list0)
        for x in c:
          print x, '#'*c[x]
        

        【讨论】:

          【解决方案7】:
          import bisect
          from collections import defaultdict
          lis1 = [['Country1', 142.8576737907048, 207.69725105029553, 21.613192419863577, 15.129178465784218],
          ['Country2', 109.33326343550823, 155.6847323746669, 15.450489646386226, 14.131554442715336],
          ['Country3', 99.23033109735835, 115.37122637190915, 5.380298424850267, 5.422030104456135],
          ]
          lis2 = [0, 100, 1000, 1000]
          
          dic = defaultdict(int)
          
          for x in lis1:
                 x = x[1]
                 ind=bisect.bisect(lis2,x) 
                 if not (x >= lis2[-1] or x <= lis2[0]):
                     sm, bi = lis2[ind-1], lis2[ind]
                     dic ["{} <= {} <= {}".format(sm ,x, bi)] +=1
          for k,v in dic.items():
              print k,'-->',v
          

          输出:

          0 <= 99.2303310974 <= 100 --> 1
          100 <= 142.857673791 <= 1000 --> 1
          100 <= 109.333263436 <= 1000 --> 1
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-05
            • 2012-05-24
            • 1970-01-01
            • 2020-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多