Как построить гистограмму Python, используя векторизованный условный счет - PullRequest
0 голосов
/ 20 сентября 2018

Я работаю над новым стандартным классом гистограмм для Python (в идеале, чтобы способствовать NumPy, учитывая многочисленные серьезные недостатки, которые я испытал при использовании стандартной реализации при выполнении оценки плотности во время моего Masters).

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

В примере кода, который успешно суммирует количество точек в каждой ячейке, вы можете запустить нижеприведенную диаграмму, которая также создает график, подобный следующему:

График простых бинов

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches

class Custom_Histogram():

    def __init__(self, df, bins=None): 

        self.DF = df 
        self.bins = np.array(bins)
        self.n_dims = len(df.columns.values)

        ## Count number of datapoints in each bin
        self.hist = np.array([  
                    np.sum(     (self.DF.iloc[:,:] >= self.bins[:,:,0][i][:]) & 
                                (self.DF.iloc[:,:] <  self.bins[:,:,1][i][:])
                       )
                       for i in range(len(self.bins)) ], dtype=np.int32)[:,0]


## Generate Random Data
N = 200
X = np.random.normal(0.5,0.15,N)
Y = np.random.normal(0.5,0.05,N)
## Populate a Pandas DataFrame
DF = pd.DataFrame({'x':X,'y':Y})

## Hardcoded, contiguous, 2D variable-area bins
bins = np.array([
            [[0.0,0.2],[0.0,1.5]],
            [[0.2,0.4],[0.0,1.5]],
            [[0.4,0.6],[0.0,1.5]],
            [[0.6,0.8],[0.0,1.5]],
            [[0.8,1.0],[0.0,1.5]]
            ])

## Generate histogram using custom bins
Hist = Custom_Histogram(DF, bins)
print('Histogram: ', Hist.hist)

## 2D Plot
fig, axes = plt.subplots(figsize=(4, 3.5))

plt.scatter(DF.iloc[:,0], DF.iloc[:,1], 5, 'k')

# Create a patch for each bin and plot
for i,bin in enumerate(bins):
    rect = patches.Rectangle(   (bin[0][0],bin[1][0]),
                                bin[0][1]-bin[0][0],
                                bin[1][1]-bin[1][0],
                                linewidth=1,
                                edgecolor='r',facecolor='none')
    axes.add_patch(rect)
    axes.set_ylim(-0.5,2)
    axes.set_xlim(-0.5,1.5)

print('Histogram Sum: ', np.sum(Hist.hist))
print('Data Points: ', N)

plt.show()

С более сложными бинами количество точек больше не является правильным, а некоторые, кажется, считаются дважды.Попытка с ячейками:

bins = np.array([
            [[0.0,0.2],[0.0,1.5]],
            [[0.2,0.4],[0.0,1.5]],
            [[0.4,0.6],[0.0,1.0]],
            [[0.4,0.6],[1.0,1.5]],
            [[0.6,0.8],[0.0,0.5]],
            [[0.6,0.8],[0.5,1.5]],
            [[0.8,1.0],[0.0,1.5]]
            ])

, которая строится как: Сложная ячейка с ячейками , возвращает больше точек, чем существует.

Поэтому я хотел бы знать, как изменитьлогика заключается в подсчете точек данных, но сохранении их эффективным векторным способом (я убежден, что здесь нет необходимости в каких-либо циклах).Мне также нужно, чтобы это охватывало разные измерения, что, кажется, уже почти работает (структура срезов правильно выполняет условие в каждом измерении, но происходит что-то еще, что вызывает тот же тип двойного счета, что и выше).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...