bin один столбец и сумма другого (2, N) массива - PullRequest
1 голос
/ 12 марта 2019

Вопрос:

У меня есть набор данных, подобный следующему:

import numpy as np 
x = np.arange(0,10000,0.5)
y = np.arange(x.size)/x.size

Построение графика в пространстве журнала журнала, это выглядит так:

import matplotlib.pyplot as plt
plt.loglog(x, y)
plt.show()

enter image description here

Очевидно, что на этом графике журнала есть много избыточной информации. Мне не нужно 10000 баллов, чтобы представить эту тенденцию.

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

Попытка:

Сначала я создаю корзины, которые хочу использовать для x.

# need a nicer way to do this.
# what if I want more than 10 bins per order of magnitude? 
bins = 10**np.arange(1,int(round(np.log10(x.max()))))
bins = np.unique((bins.reshape(-1,1)*np.arange(0,11)).flatten())

#array([    0,     10,    20,    30,    40,    50,    60,    70,    80,
#          90,   100,   200,   300,   400,   500,   600,   700,   800,
#         900,  1000,  2000,  3000,  4000,  5000,  6000,  7000,  8000,
#        9000, 10000])

Во-вторых, я нахожу индекс корзины, которой соответствует каждый элемент x:

digits = np.digitize(x, bins) 

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

# need a nicer way to do this.. is there an np.searchsorted() solution?
# this way is quick and dirty, but it does not scale with acceptable speed
averages = []
for d in np.unique(digits):
    mask = digits==d
    y_mean = np.mean(y[mask])
    averages.append(y_mean)
del mask, y_mean, d    

# now plot the averages within each bin against the center of each bin 
plt.loglog((bins[1:]+bins[:-1])/2.0, averages)
plt.show()

enter image description here

Резюме: Есть ли более плавный способ сделать это? Как я могу генерировать произвольные n точек на порядок вместо 10?

1 Ответ

1 голос
/ 12 марта 2019

Я отвечу на два из ваших нескольких вопросов: Как поочередно создавать ячейки и генерировать произвольные n точек на порядок вместо 10?

Вы можете использовать np.logspace и np.outer, чтобы создать свои ячейки для любого произвольного значения n, как показано ниже. База по умолчанию в logspace равна 10. Она генерирует логарифмически разнесенные точки, аналогичные linspace, которая генерирует линейно разнесенную сетку.

Для n=10

n = 10
bins = np.unique(np.outer(np.logspace(0, 3, 4), np.arange(0, n+1)))
# array([0.e+00, 1.e+00, 2.e+00, 3.e+00, 4.e+00, 5.e+00, 6.e+00, 7.e+00,
#        8.e+00, 9.e+00, 1.e+01, 2.e+01, 3.e+01, 4.e+01, 5.e+01, 6.e+01,
#        7.e+01, 8.e+01, 9.e+01, 1.e+02, 2.e+02, 3.e+02, 4.e+02, 5.e+02,
#        6.e+02, 7.e+02, 8.e+02, 9.e+02, 1.e+03, 2.e+03, 3.e+03, 4.e+03,
#        5.e+03, 6.e+03, 7.e+03, 8.e+03, 9.e+03, 1.e+04])

Для n=20

n = 20
bins = np.unique(np.outer(np.logspace(0, 3, 4), np.arange(0, n+1)))
# array([0.0e+00, 1.0e+00, 2.0e+00, 3.0e+00, 4.0e+00, 5.0e+00, 6.0e+00, 7.0e+00, 8.0e+00, 9.0e+00, 1.0e+01, 1.1e+01, 1.2e+01, 1.3e+01, 1.4e+01, 1.5e+01, 1.6e+01, 1.7e+01, 1.8e+01, 1.9e+01, 2.0e+01, 3.0e+01, 4.0e+01, 5.0e+01, 6.0e+01, 7.0e+01, 8.0e+01, 9.0e+01, 1.0e+02, 1.1e+02, 1.2e+02, 1.3e+02, 1.4e+02, 1.5e+02, 1.6e+02, 1.7e+02, 1.8e+02, 1.9e+02, 2.0e+02, 3.0e+02, 4.0e+02, 5.0e+02, 6.0e+02, 7.0e+02, 8.0e+02, 9.0e+02, 1.0e+03, 1.1e+03, 1.2e+03, 1.3e+03, 1.4e+03, 1.5e+03, 1.6e+03, 1.7e+03, 1.8e+03, 1.9e+03, 2.0e+03, 3.0e+03, 4.0e+03, 5.0e+03, 6.0e+03, 7.0e+03, 8.0e+03, 9.0e+03, 1.0e+04, 1.1e+04, 1.2e+04, 1.3e+04, 1.4e+04, 1.5e+04, 1.6e+04, 1.7e+04, 1.8e+04, 1.9e+04, 2.0e+04])

EDIT

Если вы хотите 0, 10, 20, 30...90, 100, 200, 300..., вы можете сделать следующее

n = 10
bins = np.unique(np.outer(np.logspace(1, 3, 3), np.arange(0, n+1)))
# array([    0.,    10.,    20.,    30.,    40.,    50.,    60.,    70.,
#           80.,    90.,   100.,   200.,   300.,   400.,   500.,   600.,
#          700.,   800.,   900.,  1000.,  2000.,  3000.,  4000.,  5000.,
#         6000.,  7000.,  8000.,  9000., 10000.])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...