Подтвердить что ты не робот

Кумулятивные графики распределения python

Я делаю проект с использованием python, где у меня есть два массива данных. Пусть назовем их pc и pnc. Мне нужно построить кумулятивное распределение обоих из них на одном графике. Для pc предполагается, что он меньше графика, то есть at (x, y), y точек в pc должны иметь значение меньше x. Для pnc оно должно быть больше, чем график, т.е. В точке (x, y), y точек в pnc должны иметь значение больше, чем x.

Я попытался использовать функцию гистограммы - pyplot.hist. Есть ли лучший и простой способ делать то, что я хочу? Кроме того, он должен быть нанесен на логарифмическую шкалу по оси x.

4b9b3361

Ответ 1

Ты был близок. Вы не должны использовать plt.hist как numpy.histogram, который дает вам как значения, так и бункеры, чем вы можете построить кумулятивный с легкостью:

import numpy as np
import matplotlib.pyplot as plt

# some fake data
data = np.random.randn(1000)
# evaluate the histogram
values, base = np.histogram(data, bins=40)
#evaluate the cumulative
cumulative = np.cumsum(values)
# plot the cumulative function
plt.plot(base[:-1], cumulative, c='blue')
#plot the survival function
plt.plot(base[:-1], len(data)-cumulative, c='green')

plt.show()

enter image description here

Ответ 2

Использование гистограмм действительно излишне тяжело и неточно (биннинг делает данные нечеткими): вы можете просто отсортировать все значения x: индекс каждого значения - это количество меньших значений. Это более короткое и простое решение выглядит следующим образом:

import numpy as np
import matplotlib.pyplot as plt

# Some fake data:
data = np.random.randn(1000)

sorted_data = np.sort(data)  # Or data.sort(), if data can be modified

# Cumulative counts:
plt.step(sorted_data, np.arange(sorted_data.size))  # From 0 to the number of data points-1
plt.step(sorted_data[::-1], np.arange(sorted_data.size))  # From the number of data points-1 to 0

plt.show()

Кроме того, более подходящий стиль сюжета действительно plt.step() вместо plt.plot(), поскольку данные находятся в дискретных точках.

Результат:

enter image description here

Вы можете видеть, что он больше рваный, чем результат ответа EnricoGiampieri, но это реальная гистограмма (вместо того, чтобы быть приблизительной, более суровой версией).

PS. Как заметил Себастьян Рашка, последний пункт должен идеально показать общее количество (вместо общего счета-1). Это может быть достигнуто с помощью:

plt.step(np.concatenate([sorted_data, sorted_data[[-1]]]),
         np.arange(sorted_data.size+1))
plt.step(np.concatenate([sorted_data[::-1], sorted_data[[0]]]),
         np.arange(sorted_data.size+1))

В data так много точек, что эффект не отображается без масштабирования, но самая последняя точка в общем счетчике имеет значение, когда данные содержат только несколько точек.

Ответ 3

После окончательного обсуждения с @EOL я хотел опубликовать свое решение (в верхнем левом углу), используя случайный образец Гаусса в виде сводки:

enter image description here

import numpy as np
import matplotlib.pyplot as plt
from math import ceil, floor, sqrt

def pdf(x, mu=0, sigma=1):
    """
    Calculates the normal distribution probability density 
    function (PDF).  

    """
    term1 = 1.0 / ( sqrt(2*np.pi) * sigma )
    term2 = np.exp( -0.5 * ( (x-mu)/sigma )**2 )
    return term1 * term2


# Drawing sample date poi
##################################################

# Random Gaussian data (mean=0, stdev=5)
data1 = np.random.normal(loc=0, scale=5.0, size=30)
data2 = np.random.normal(loc=2, scale=7.0, size=30)
data1.sort(), data2.sort()

min_val = floor(min(data1+data2))
max_val = ceil(max(data1+data2))

##################################################




fig = plt.gcf()
fig.set_size_inches(12,11)

# Cumulative distributions, stepwise:
plt.subplot(2,2,1)
plt.step(np.concatenate([data1, data1[[-1]]]), np.arange(data1.size+1), label='$\mu=0, \sigma=5$')
plt.step(np.concatenate([data2, data2[[-1]]]), np.arange(data2.size+1), label='$\mu=2, \sigma=7$') 

plt.title('30 samples from a random Gaussian distribution (cumulative)')
plt.ylabel('Count')
plt.xlabel('X-value')
plt.legend(loc='upper left')
plt.xlim([min_val, max_val])
plt.ylim([0, data1.size+1])
plt.grid()

# Cumulative distributions, smooth:
plt.subplot(2,2,2)

plt.plot(np.concatenate([data1, data1[[-1]]]), np.arange(data1.size+1), label='$\mu=0, \sigma=5$')
plt.plot(np.concatenate([data2, data2[[-1]]]), np.arange(data2.size+1), label='$\mu=2, \sigma=7$') 

plt.title('30 samples from a random Gaussian (cumulative)')
plt.ylabel('Count')
plt.xlabel('X-value')
plt.legend(loc='upper left')
plt.xlim([min_val, max_val])
plt.ylim([0, data1.size+1])
plt.grid()


# Probability densities of the sample points function
plt.subplot(2,2,3)

pdf1 = pdf(data1, mu=0, sigma=5)
pdf2 = pdf(data2, mu=2, sigma=7)
plt.plot(data1, pdf1, label='$\mu=0, \sigma=5$')
plt.plot(data2, pdf2, label='$\mu=2, \sigma=7$')

plt.title('30 samples from a random Gaussian')
plt.legend(loc='upper left')
plt.xlabel('X-value')
plt.ylabel('probability density')
plt.xlim([min_val, max_val])
plt.grid()


# Probability density function
plt.subplot(2,2,4)

x = np.arange(min_val, max_val, 0.05)

pdf1 = pdf(x, mu=0, sigma=5)
pdf2 = pdf(x, mu=2, sigma=7)
plt.plot(x, pdf1, label='$\mu=0, \sigma=5$')
plt.plot(x, pdf2, label='$\mu=2, \sigma=7$')

plt.title('PDFs of Gaussian distributions')
plt.legend(loc='upper left')
plt.xlabel('X-value')
plt.ylabel('probability density')
plt.xlim([min_val, max_val])
plt.grid()

plt.show()