Как получить QQ-график для распределения Парето в Python? - PullRequest
0 голосов
/ 24 августа 2018

Графики QQ используются для получения достоверного соответствия между набором точек данных и теоретическим распределением.Ниже приведена процедура получения баллов.

  1. Выберите образцы для использования.Сортируйте выбранные образцы с помощью X (i), обозначающего i-й образец
  2. . Найдите значения модели, которые соответствуют образцам.Это делается в два этапа:

    a.Свяжите каждый образец с процентилем, который он представляет.пи = (i-0,5) / n

    b.Рассчитайте значение модели, которое будет связано с этим процентилем.Это делается путем инвертирования CDF модели, как это делается при генерации случайных отклонений от распределения модели.Таким образом, значением модели, соответствующей выборке i, является Finverse (pi).

    c.Нарисуйте график QQ, используя n точек

(X (i), Finverse (pi)) 1 ≤ i ≤ n

Используя этот подход, я придумалследующая реализация Python.

_distn_names = ["pareto"]
def fit_to_all_distributions(data):
    dist_names = _distn_names

    params = {}
    for dist_name in dist_names:
        try:
            dist = getattr(st, dist_name)
            param = dist.fit(data)

            params[dist_name] = param
        except Exception:
            print("Error occurred in fitting")
            params[dist_name] = "Error"

    return params 

def get_q_q_plot(values, dist, params):
    values.sort()

    arg = params[:-2]
    loc = params[-2]
    scale = params[-1]

    x = []

    for i in range(len(values)):
        x.append((i-0.5)/len(values))

    y = getattr(st, dist).ppf(x, loc=loc, scale=scale, *arg)

    y = list(y)

    emp_percentiles = values
    dist_percentiles = y

    print("Emperical Percentiles")
    print(emp_percentiles)

    print("Distribution Percentiles")
    print(dist_percentiles)

    plt.figure()
    plt.xlabel('dist_percentiles')
    plt.ylabel('actual_percentiles')
    plt.title('Q Q plot')
    plt.plot(dist_percentiles, emp_percentiles)
    plt.savefig("/path/q-q-plot.png")

b = 2.62
latencies = st.pareto.rvs(b, size=500)
data = pd.Series(latencies)
params = fit_to_all_distributions(data)

pareto_params = params["pareto"]

get_q_q_plot(latencies, "pareto", pareto_params)

В идеале я должен получить прямую линию, но это то, что я получаю.

QQ plot

Почему я не получаю прямую линию?Что-то не так в моей реализации?

1 Ответ

0 голосов
/ 16 мая 2019

Вы можете получить график QQ для любого распределения (в статистике scipy их 82), используя следующий код.

import os
import matplotlib.pyplot as plt
import sys
import math
import numpy as np
import scipy.stats as st
from scipy.stats._continuous_distns import _distn_names
from scipy.optimize import curve_fit

def get_q_q_plot(latency_values, distribution):

    distribution = getattr(st, distribution)
    params = distribution.fit(latency_values)

    latency_values.sort()

    arg = params[:-2]
    loc = params[-2]
    scale = params[-1]

    x = []

    for i in range(1, len(latency_values)):
        x.append((i-0.5) / len(latency_values))

    y = distribution.ppf(x, loc=loc, scale=scale, *arg)

    y = list(y)

    emp_percentiles = latency_values[1:]
    dist_percentiles = y

    return emp_percentiles, dist_percentiles
...