Как связать серию значений с плавающей запятой в гистограмму в Python?

У меня есть набор значений в float (всегда меньше 0). Который я хочу вставить в гистограмму, т.е. каждый столбец в гистограмме содержит диапазон значений [0,0,150)

Данные у меня выглядят так:

0.000
0.005
0.124
0.000
0.004
0.000
0.111
0.112

С моим кодом ниже я ожидаю получить результат, который выглядит как

[0, 0.005) 5
[0.005, 0.011) 0
...etc.. 

Я пытался сделать такой биннинг с этим моим кодом. Но, похоже, это не работает. Как правильно это сделать?

#! /usr/bin/env python


import fileinput, math

log2 = math.log(2)

def getBin(x):
    return int(math.log(x+1)/log2)

diffCounts = [0] * 5

for line in fileinput.input():
    words = line.split()
    diff = float(words[0]) * 1000;

    diffCounts[ str(getBin(diff)) ] += 1

maxdiff = [i for i, c in enumerate(diffCounts) if c > 0][-1]
print maxdiff
maxBin = max(maxdiff)


for i in range(maxBin+1):
     lo = 2**i - 1
     hi = 2**(i+1) - 1
     binStr = '[' + str(lo) + ',' + str(hi) + ')'
     print binStr + '\t' + '\t'.join(map(str, (diffCounts[i])))

~


person neversaint    schedule 12.11.2009    source источник
comment
Ну, в примере, что вы ожидаете..., если у вас есть диапазоны, определенные как [0, 0,005) (справа открыт) и [0,005, 0,011) (закрыт слева), тогда вывод должен быть: [0, 0,005) 4 [ 0,005, 0,011) 1 и т.д...   -  person Gacek    schedule 12.11.2009
comment
Кажется, не работает? Какая-то конкретная жалоба? Или вы ожидаете, что все должны запустить его и попытаться угадать, что вам не нравится в выводе?   -  person S.Lott    schedule 12.11.2009
comment
Чтобы не изобретать велосипед заново, особенно если следующим шагом будет построение гистограммы: вам следует подумать об использовании фреймворка Matplotlib, который обрабатывает все это.   -  person RedGlyph    schedule 12.11.2009


Ответы (2)


По возможности не изобретайте велосипед. В NumPy есть все, что вам нужно:

#!/usr/bin/env python
import numpy as np

a = np.fromfile(open('file', 'r'), sep='\n')
# [ 0.     0.005  0.124  0.     0.004  0.     0.111  0.112]

# You can set arbitrary bin edges:
bins = [0, 0.150]
hist, bin_edges = np.histogram(a, bins=bins)
# hist: [8]
# bin_edges: [ 0.    0.15]

# Or, if bin is an integer, you can set the number of bins:
bins = 4
hist, bin_edges = np.histogram(a, bins=bins)
# hist: [5 0 0 3]
# bin_edges: [ 0.     0.031  0.062  0.093  0.124]
person unutbu    schedule 12.11.2009
comment
А если вам нужна нормализованная гистограмма, вы можете добавить строку: гист = гист*1.0/сумма(гист) - person dval; 05.12.2015
comment
И если вы хотите, чтобы интеграл по диапазону ячеек был равен 1, используйте density=True. - person unutbu; 05.12.2015

Первая ошибка:

Traceback (most recent call last):
  File "C:\foo\foo.py", line 17, in <module>
    diffCounts[ str(getBin(diff)) ] += 1
TypeError: list indices must be integers

Почему вы конвертируете int в str, когда нужна str? Исправьте это, тогда мы получим:

Traceback (most recent call last):
  File "C:\foo\foo.py", line 17, in <module>
    diffCounts[ getBin(diff) ] += 1
IndexError: list index out of range

потому что вы сделали только 5 ведер. Я не понимаю вашу схему группирования, но давайте сделаем 50 сегментов и посмотрим, что произойдет:

6
Traceback (most recent call last):
  File "C:\foo\foo.py", line 21, in <module>
    maxBin = max(maxdiff)
TypeError: 'int' object is not iterable

maxdiff — это единственное значение из вашего списка целых чисел, так что же здесь делает max? Удалим его, теперь получим:

6
Traceback (most recent call last):
  File "C:\foo\foo.py", line 28, in <module>
    print binStr + '\t' + '\t'.join(map(str, (diffCounts[i])))
TypeError: argument 2 to map() must support iteration

Конечно же, вы используете одно значение в качестве второго аргумента для map. Упростим из этого последние две строчки:

 binStr = '[' + str(lo) + ',' + str(hi) + ')'
 print binStr + '\t' + '\t'.join(map(str, (diffCounts[i])))

к этому:

 print "[%f, %f)\t%r" % (lo, hi, diffCounts[i])

Теперь печатает:

6
[0.000000, 1.000000)    3
[1.000000, 3.000000)    0
[3.000000, 7.000000)    2
[7.000000, 15.000000)   0
[15.000000, 31.000000)  0
[31.000000, 63.000000)  0
[63.000000, 127.000000) 3

Я не уверен, что еще здесь делать, так как я действительно не понимаю, как вы надеетесь использовать ведро. Кажется, это связано с бинарными полномочиями, но для меня это не имеет смысла...

person Ned Batchelder    schedule 12.11.2009