создание бинплот в binned в matplotlib с numpy и scipy в Python - PullRequest
3 голосов
/ 27 апреля 2010

У меня есть двумерный массив, содержащий пары значений, и я хотел бы составить коробочную диаграмму из значений y с помощью различных элементов x. То есть если массив:

my_array = array([[1, 40.5], [4.5, 60], ...]])

тогда я бы хотел скомпоновать my_array [:, 0], а затем для каждого из бинов создать блок-график соответствующих значений my_array [:, 1], попадающих в каждый блок. Итак, в конце я хочу, чтобы на графике было много бин-много коробочных графиков.

Я попробовал следующее:

min_x = min(my_array[:, 0])
max_x = max(my_array[:, 1])

num_bins = 3
bins = linspace(min_x, max_x, num_bins)
elts_to_bins = digitize(my_array[:, 0], bins)

Однако, это дает мне значения в elts_to_bins, которые варьируются от 1 до 3. Я думал, что я должен получить индексы на основе 0 для бинов, и я хотел только 3 бина. Я предполагаю, что это из-за некоторой хитрости с тем, как бины представлены в linspace vs. digitalize.

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

спасибо.

Ответы [ 2 ]

7 голосов
/ 27 апреля 2010

Вы получаете 3-й бин для максимального значения в массиве (я предполагаю, что у вас есть опечатка, и max_x должно быть "max (my_array [:, 0])" вместо "max (my_array [ : 1]) "). Вы можете избежать этого, добавив 1 (или любое положительное число) к последней корзине.

Кроме того, если я вас правильно понимаю, вы хотите связать одну переменную с другой, так что мой пример ниже показывает это. Если вы используете наборы данных (которые работают намного медленнее), в matplotlib.mlab есть несколько функций (например, mlab.rec_groupby и т. Д.), Которые делают подобные вещи.

В любом случае, в конце концов, у вас может быть что-то вроде этого (для бин x по значениям в y, если предположить, что x и y имеют одинаковую длину)

def bin_by(x, y, nbins=30):
    """
    Bin x by y.
    Returns the binned "x" values and the left edges of the bins
    """
    bins = np.linspace(y.min(), y.max(), nbins+1)
    # To avoid extra bin for the max value
    bins[-1] += 1 

    indicies = np.digitize(y, bins)

    output = []
    for i in xrange(1, len(bins)):
        output.append(x[indicies==i])

    # Just return the left edges of the bins
    bins = bins[:-1]

    return output, bins

В качестве быстрого примера:

In [3]: x = np.random.random((100, 2))

In [4]: binned_values, bins = bin_by(x[:,0], x[:,1], 2)

In [5]: binned_values
Out[5]: 
[array([ 0.59649575,  0.07082605,  0.7191498 ,  0.4026375 ,  0.06611863,
        0.01473529,  0.45487203,  0.39942696,  0.02342408,  0.04669615,
        0.58294003,  0.59510434,  0.76255006,  0.76685052,  0.26108928,
        0.7640156 ,  0.01771553,  0.38212975,  0.74417014,  0.38217517,
        0.73909022,  0.21068663,  0.9103707 ,  0.83556636,  0.34277006,
        0.38007865,  0.18697416,  0.64370535,  0.68292336,  0.26142583,
        0.50457354,  0.63071319,  0.87525221,  0.86509534,  0.96382375,
        0.57556343,  0.55860405,  0.36392931,  0.93638048,  0.66889756,
        0.46140831,  0.01675165,  0.15401495,  0.10813141,  0.03876953,
        0.65967335,  0.86803192,  0.94835281,  0.44950182]),
 array([ 0.9249993 ,  0.02682873,  0.89439141,  0.26415792,  0.42771144,
        0.12292614,  0.44790357,  0.64692616,  0.14871052,  0.55611472,
        0.72340179,  0.55335053,  0.07967047,  0.95725514,  0.49737279,
        0.99213794,  0.7604765 ,  0.56719713,  0.77828727,  0.77046566,
        0.15060196,  0.39199123,  0.78904624,  0.59974575,  0.6965413 ,
        0.52664095,  0.28629324,  0.21838664,  0.47305751,  0.3544522 ,
        0.57704906,  0.1023201 ,  0.76861237,  0.88862359,  0.29310836,
        0.22079126,  0.84966201,  0.9376939 ,  0.95449215,  0.10856864,
        0.86655289,  0.57835533,  0.32831162,  0.1673871 ,  0.55742108,
        0.02436965,  0.45261232,  0.31552715,  0.56666458,  0.24757898,
        0.8674747 ])]

Надеюсь, это немного поможет!

4 голосов
/ 27 апреля 2010

Numpy имеет выделенную функцию для создания гистограмм так, как вам нужно:

histogram(a, bins=10, range=None, normed=False, weights=None, new=None)

который вы можете использовать как:

(hist_data, bin_edges) = histogram(my_array[:,0], weights=my_array[:,1])

Ключевым моментом здесь является использование аргумента weights: каждое значение a[i] будет вносить weights[i] в гистограмму. Пример:

a = [0, 1]
weights = [10, 2]

описывает 10 точек при x = 0 и 2 точки при x = 1.

С помощью аргумента bins вы можете установить количество бинов или их пределы (подробнее см. Официальную документацию 1019 *).

Гистограмма может быть построена с помощью чего-то вроде:

bar(bin_edges[:-1], hist_data)

Если вам нужно только построить гистограмму plot , аналогичная функция hist () может напрямую построить гистограмму:

hist(my_array[:,0], weights=my_array[:,1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...