2015-10-25 3 views
0

Я пытаюсь построить простую гистограмму. Я обработал свои данные в виде списка: X = [30, 2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225, 2359, 2138 ...]Гистограмма Matplotlib

где каждое положение соответствует к числу элементов с этим значением (так что 30 элементов для 0, 2728 для 1 и т. д.) Если я построю этот список в виде гистограммы, я получаю желаемый результат, но разрешение слишком велико (т.е. каждое значение является ведром). То, что я хочу сделать, это объединить ведра, чтобы я мог получить как мои значения X: 0, 1-10, 10-50, 50-150, 150-500, так и Y - сумму элементов в нужном диапазоне, поэтому для 0 У меня будет значение y 30, для 1-10 я буду иметь сумму суммы (2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225) и т. Д.

Я пробовал так:

plt.hist(X,bins=[0,1,10]) 

, но я не получаю желаемый результат, я ожидаю получить один бар 0-1 с у = 30 и второй строка 1-10 с у = 24785, но это не то, что он строит.

Каков наилучший способ для этого?

ответ

0

Вы хотите объединить ведра в настраиваемый список: 0, 1-10, 10-50, 50-150, 150-500. Поскольку это индивидуальный список, я не уверен, можете ли вы прямо сообщить plt.hist, что такое корзины. Я бы предложил вручную подсчитать, сколько значений находится в каждом из настроенных бункеров. Это очень помогает, если вы преобразуете свой список X в массив NumPy, используя np.array().

X = np.array([30, 2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225, 2359, 2138]) 
    ##Customized bin list: 
    bin_list = np.array([0,1,10,50,150, 500, np.inf ]) ##Can specify 500 to be inf as well 
    plot_bin = np.zeros(len(bin_list)-1) 
    for bin_n in range(len(bin_list)-1): 
     plot_bin[bin_n] = np.sum((X >= bin_list[bin_n]) & (X < bin_list[bin_n+1])) 

    ## Create string version of the buckets to use as labels 
    str_bin_list_lower = [str(a) for a in bin_list[0: -1 ]] 
    x_ticks = np.arange(len(bin_list)-1)-0.35 
    plt.bar(x_ticks, plot_bin) 
    plt.xticks(x_ticks+0.35, str_bin_list_lower) 

Отредактировано: Я неправильно понял ваш вопрос. У вас есть список bin [0,10,50] и вы хотите добавить числа из [0], [1-10], [10-50] и т. Д. Вам лучше знать, как элементы индекса Python. Например, range(10)[0:5] = [0,1,2,3,4] и range(10)[5:10] = [5,6,7,8,9]. Вы должны учитывать это, когда делаете свой список бинов. Тогда процесс биннинга должен быть:

X = np.array([30, 2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225, 2359, 2138]) 
    bin_list = np.array([0,10,50,150, 500, np.inf ])+1 ##Can specify 500 
    plot_bin = np.zeros(len(bin_list)-1) 
    for bin_n in range(len(bin_list)-1): 
     if bin_n==len(bin_list)-2: 
     plot_bin[bin_n] = np.sum(X[ bin_list[bin_n]: ]) 
     else: 
     plot_bin[bin_n] = np.sum(X[ bin_list[bin_n]:bin_list[bin_n+1]+1]) 
    plot_bin = np.insert(plot_bin, 0, X[0]) 
+0

Я думаю, что это правильный подход, но plot_bin [0. 0. 1. 0. 0. 12.], в то время как это должно быть [30,24785,4497 , 0,0,0] (поскольку сумма значений между индексом 0 и индексом 1 равна 30, сумма значений между индексом 1 и индексом 10 равна 24785, а сумма значений между индексом 10 и индексом 50 равна 4497, и нет элементов в массиве с индексом> 12, чтобы оставшиеся ведра были пустыми). Я думаю, что могу либо вручную переупаковать мои данные, либо использовать np умным способом (например, ваш ответ подсказывает). –

+0

Ах, я вижу, что я неправильно понял ваш первоначальный вопрос. Где вы получаете 24785 и 4497? В целом, я думаю, вы можете использовать 'np', чтобы получить данные так, как вы этого хотите. – Julien

+0

Я суммирую все значения по индексу 1:10 (2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225), вот как я получаю 24785. Затем я суммирую индекс 10:50 (2359, 2138) который дает мне 4497. –

1

Для пути вы Preprocess данные, правильный путь, чтобы построить это:

X = [30, 2728, 2894, 2582, 2309, 2396, 2491, 2453, 2382, 2325, 2225, 2359, 2138] 
plt.bar(range(len(X)),X); 

enter image description here

Однако matplotlib обеспечивает еще более легкий и простой способ построить гистограмму:

x = np.random.randn(1000) 
plt.hist(x, bins=30); 

enter image description here

Если вы хотите более прямой контроля над биннингом, вы можете переключиться на панда и попробовать pd.cut, где вы можете определить свои собственные контейнеры:

import pandas as pd 
df = pd.DataFrame({'x':np.random.randint(0,100,1000)}) 
factor = pd.cut(df.x, [1,10,20,100]) 
df.groupby(factor).apply(lambda x: x.count()).plot(kind='bar', rot=45, legend=0); 

enter image description here

+0

Вот что я говорю, в plt.bar (диапазон (LEN (X)), X); метод работает, но я хочу объединить ведра. Как их объединить? –

+1

@StefanD Я думаю, что самый простой способ нарисовать хорошую гистограмму - правильно обработать ваши данные, а затем вызвать 'plt.hist()' или pandas 'pd.hist()' matplotlib. Зачем вам (1) выбивать ваши данные, а затем (2) повторно заново складывать его после того, как вы обнаружили, что гистограмма (на самом деле это штриховой график) не так хороша, как вы надеялись?Если вам не нравится биннинг, который вы получаете, я думаю, вам следует отступить и повторно собрать ваши данные. –

+0

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

Смежные вопросы