Бинирование списка в python

Прежде всего, я хотел бы сказать, что я новичок в python, и этот код был создан с учетом советов и предложений пользователей на stackoverflow. Код показан ниже:

f = open('E:\Python27\WASP DATA\Sample Data.txt',"r")
num=0
line = f.readlines()

X = []
for n, lines in enumerate(line, 0):  #6621
        # make it 109 to remove the first line "['# Column 3: Magnitude error\n']"
    if (n > 109): 
        linSplit = lines.split('    ')
        joined = ' '.join(linSplit)
            # apply the float function to every item in joined.split
            # create a new list of floats in tmp variable
        tmp = map((lambda x: float(x)), joined.split())
        X.append(tmp)

#print X[0] # print first element in the list

Period_1 = float(line[28][23:31])
Epoch_1 = float(line[27][22:31])
Period_2 = float(line[44][23:31])
Epoch_2 = float(line[43][22:31])
#Period_3 = float(line[60][23:31])
#Epoch_3 = float(line[59][22:31])
#Period_4 = float(line[76][23:31])
#Epoch_4 = float(line[75][22:31])
#Period_5 = float(line[108][23:31])
#Epoch_5 = float(line[91][22:31])

print("The time periods are:")
print Period_1
print Period_2
#print Period_3
#print Period_4
#print Period_5 

print("\nThe Epoch times are:")
print Epoch_1
print Epoch_2
#print Epoch_3
#print Epoch_4
#print Epoch_5
print('respectively.')

P = []
phase_var = float

for j in range(0,len(X),1):
    phase_var = (X[j][0] + (10*Period_1) - Epoch_1)/Period_1
    P.append(phase_var)

print P[0]

for m in range(0,len(P),1):
    P[m]=float(P[m]-int(P[m]))

#print P[0]

Mag = []

for n in range(0,len(X),1):
    temp = X[n][1]
    Mag.append(temp)

#print Mag[0]
#print X[0]

from pylab import *

#Plotting the first scatter diagram to see if data is phased correctly.

#plot(P, Mag)
scatter(P, Mag)
xlabel('Phase (Periods)')
ylabel('Magnitude')
#title('Dunno yet')
grid(True)
savefig("test.png")
show()

#Bin the data to create graph where magnitudes are averaged, and B lets us mess around with the binning resolution, and reducing effect of extraneous data points.  

B = 2050
minv = min(P)
maxv = max(P)
bincounts = []
for i in range(B+1):
    bincounts.append(0)
for d in P:
    b = int((d - minv) / (maxv - minv) * B)
    bincounts[b] += 1

# plot new scatter

scatter(bincounts, Mag)
show()

Исходный график представляет собой график рассеяния P и Mag. Однако есть несколько очков Mag для каждого периода времени. Я надеюсь попытаться создать новый разброс, в котором я могу взять все эти значения Y и усреднить их для каждого отдельного значения X, тем самым создав более плотный график с двумя провалами.

Я пробовал рассматривать различные способы группирования данных, однако независимо от того, какой метод я использую, график, содержащий объединенные данные, не отображается правильно. Значения X должны варьироваться от 0 до 1, как на предварительно сгруппированном графике данных.

Это данные, с которыми я работаю, на всякий случай, если вам нужно их увидеть.

http://pastebin.com/60E84azv

Может ли кто-нибудь предложить какие-либо предложения или советы о том, как создать бинарный график данных? Мои познания в биннинге данных весьма минимальны.

Спасибо за ваше время!


person Maneesh Sharma    schedule 16.11.2013    source источник
comment
Оставляя в стороне часть графика/графика, вы пытаетесь собрать столбец 1: HJD и для каждого столбца вычислить среднее значение столбца 2: величина с поправкой на Тамуза?   -  person BiGYaN    schedule 16.11.2013
comment
По сути, да, однако бин нужно сделать с P, а столбец HJD изменится на P. Так, например, 0,0010‹P‹0,0011 он должен принимать все значения столбца 2: с поправкой на Тамуза для всех значений в списке P, которые лежат в этом диапазоне, а затем усреднить по величине, если это имеет смысл.   -  person Maneesh Sharma    schedule 16.11.2013
comment
Если вы готовы установить numpy и scipy, то stackoverflow.com/q/6163334/438758 дает хорошее решение.   -  person BiGYaN    schedule 16.11.2013
comment
хорошо, вы могли бы объяснить, что происходит с командами numpy и scipy? Я понятия не имею, что это такое, а пока я собираюсь возиться с этим кодом, чтобы попытаться понять его.   -  person Maneesh Sharma    schedule 16.11.2013


Ответы (2)


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

import numpy
import re
import matplotlib.pyplot as plt

f = open('sample_data.txt')
f.next()

pair = re.compile(r'# (.*?)[ \t]*:[ \t]*([0-9e\.-]+).*')

blocks = []
block = {}
blocks.append(block)

for line in f:
    if line[0] <> '#': 
        blocks.append(block)
        break
    line = line.strip()
    m = pair.match(line)
    if m:
        print line
        key, valstr = m.groups()
        print key, valstr
        try:
            value = float(valstr)
        except:
            value = valstr
        block[key] = value

    if (line == "#") and len(block) > 0:
        blocks.append(block)
        block = {}

peaks = sorted([block for block in blocks if 'PEAK' in block], 
               key=lambda b: b['PEAK'])
print peaks

colnames = ['HJD', 'Tamuz-corrected magnitude', 'Magnitude error']
data = numpy.loadtxt(f, [(colname, 'float64') for colname in colnames])

Nbins = 50
for peak in peaks:
    plt.figure()
    phase, _ = numpy.modf((data['HJD'] + 10*peak['Period (days)'] - peak['Epoch'])/peak['Period (days)'])
    mag = data['Tamuz-corrected magnitude']

    # use numpy.histogram to calculate the sum and the number of points in the bins
    sums, _ = numpy.histogram(phase, bins=Nbins, weights=mag)
    N, bin_edges = numpy.histogram(phase, bins=Nbins)

    # We'll plot the value at the center of each bin
    centers = (bin_edges[:-1] + bin_edges[1:])/2

    plt.scatter(phase, mag, alpha=0.2)
    plt.plot(centers, sums/N, color='red', linewidth=2)
plt.show()
person chthonicdaemon    schedule 17.11.2013
comment
Вау, это потрясающе! я все еще пытаюсь понять это, но насколько я понял, это намного эффективнее и исправляет ошибки ввода периода, которые у меня были! Спасибо!!! Я потрачу еще пару дней, чтобы выяснить, что к чему. :) - person Maneesh Sharma; 23.11.2013
comment
Без проблем. Если вы собираетесь делать многие из них, возможно, вам стоит взглянуть на Pandas. и его средства повторной выборки. - person chthonicdaemon; 24.11.2013

Полный код: http://pastebin.com/4aBjZC7Q

Вот фрагмент, выполняющий биннинг:

x = []  # Column 1: HJD
y = []  # Column 2: Tamuz-corrected magnitude

# code to read "sample_data.txt" into lists x and y
# the full code in http://pastebin.com/4aBjZC7Q includes this part as well

import numpy as np

# these will characterize the bins
startBinValue = 5060
endBinValue = 5176
binSize = 0.1

# numpy.arange() will generate the bins of size binSize in between the limiting values
bins = np.arange(startBinValue, endBinValue, binSize)
# numpy.digitize() will "bin" the values; i.e. x_binned[i] will give the bin number of value in i-th index
x_binned = np.digitize(x, bins)
y_numpyArray = np.array(y)

# There is quite a bit of jugglery here.
# x_binned==i gives a boolean of size x_binned
# y_numpyArray[x_binned==i] returns the elements of y_numpyArray where the boolean is true
# The len() check is to make sure that mean() is not called for an empty array (which results in NAN
y_means = np.array([
    y_numpyArray[x_binned == i].mean()
    if len(y_numpyArray[x_binned == i]) > 0
    else 0
    for i in range(1, len(bins))])

# binnedData is a list of tuples; tuple elements are bin's-low-limit, bin's-high-limit, y-mean value
binnedData = [(bins[i], bins[i + 1], y_means[i]) for i in range(len(y_means))]

Я сильно прокомментировал код. Но чтобы понять всю функциональность функций numpy, обратитесь к numpy .digitize(), numpy.arange()< /а>. Я использовал numpy.arange() для создания корзин. предполагая, что вы заранее знаете размеры бинов, но если вам нужно фиксированное количество бинов (скажем, 100 бинов для x-данных), используйте numpy.linspace().

person BiGYaN    schedule 16.11.2013