Как нормализовать морской участок? - PullRequest
0 голосов
/ 12 марта 2019

По причинам воспроизводимости, набора данных и по причинам воспроизводимости, я делюсь им здесь .

Вот что я делаю - из столбца 2 я читаю текущую строку и сравниваю ее со значением предыдущей строки. Если оно больше, я продолжаю сравнивать. Если текущее значение меньше значения предыдущего ряда, я хочу разделить текущее значение (меньше) на предыдущее значение (больше). Соответственно следующий код:

import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
import seaborn as sns

protocols = {}

types = {"data_v": "data_v.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }
    plt.figure(); plt.clf()
    diff=quotient_times
    plt.plot(diff, quotient, ".", label=protname, color="blue")
    plt.ylim(0, 1.0001)
    plt.title(protname)
    plt.xlabel("quotient_times")
    plt.ylabel("quotient")
    plt.legend()
    plt.show()
    sns.distplot(quotient, hist=False, label=protname)

Это дает следующие графики.

enter image description here

sns.distplot(quotient, hist=False, label=protname)

Этот фрагмент создает следующий сюжет.

enter image description here

Как видно из графиков

  • Data-V имеет коэффициент 0,8, когда quotient_times меньше 3, и коэффициент остается 0,5, если quotient_times равен больше 3.

Я хочу нормализовать значения, чтобы у нас было y-axis значений второго графика между 0 и 1. Как мы это делаем в Python?

1 Ответ

3 голосов
/ 13 марта 2019

Предисловие

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

Цитирование один ответ :

непрерывный pdf (pdf = функция плотности вероятности) никогда не говорит, что значение меньше 1, с pdf для непрерывной случайной величины, f unction p (x) не является вероятностью . Вы можете сослаться на непрерывные случайные величины и их распределения

Цитирование первого комментария к priorityofbeingernest :

Интеграл по pdf равен 1 . Здесь нет никакого противоречия.

Насколько мне известно, это CDF (функция накопленной плотности) , значения которого должны быть в [0; 1].

Примечание: все возможные функции непрерывной подгонки на сайте SciPy доступны в пакете scipy.stats

Может быть, взгляните также на функции вероятности массы ?


Если вы действительно хотите нормализовать тот же график, то вам следует собрать фактические точки данных построенной функции (Вариант 1) или определения функции (Вариант 2) и самостоятельно нормализовать их и построить их снова.

Вариант 1

enter image description here

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import sys

print('System versions          : {}'.format(sys.version))
print('System versions          : {}'.format(sys.version_info))
print('Numpy versqion           : {}'.format(np.__version__))
print('matplotlib.pyplot version: {}'.format(matplotlib.__version__))
print('seaborn version          : {}'.format(sns.__version__))

protocols = {}

types = {"data_v": "data_v.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }

    fig, (ax1, ax2) = plt.subplots(1,2, sharey=False, sharex=False)
    g = sns.distplot(quotient, hist=True, label=protname, ax=ax1, rug=True)
    ax1.set_title('basic distplot (kde=True)')
    # get distplot line points
    line = g.get_lines()[0]
    xd = line.get_xdata()
    yd = line.get_ydata()
    # https://stackoverflow.com/questions/29661574/normalize-numpy-array-columns-in-python
    def normalize(x):
        return (x - x.min(0)) / x.ptp(0)
    #normalize points
    yd2 = normalize(yd)
    # plot them in another graph
    ax2.plot(xd, yd2)
    ax2.set_title('basic distplot (kde=True)\nwith normalized y plot values')

    plt.show()

Вариант 2

Ниже я попытался выполнить kde и нормализовать полученную оценку. Я не специалист по статистике, поэтому использование kde может быть в некотором смысле неправильным (это отличается от seaborn, как можно видеть на скриншоте, это потому, что seaborn делает работу намного лучше, чем я. Он только пытался подражать kde подходит для scipy. Результат не так плох, я думаю )

Скриншот:

enter image description here

Код:

import numpy as np
from scipy import stats
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import sys

print('System versions          : {}'.format(sys.version))
print('System versions          : {}'.format(sys.version_info))
print('Numpy versqion           : {}'.format(np.__version__))
print('matplotlib.pyplot version: {}'.format(matplotlib.__version__))
print('seaborn version          : {}'.format(sns.__version__))

protocols = {}

types = {"data_v": "data_v.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }

    fig, (ax1, ax2, ax3, ax4) = plt.subplots(1,4, sharey=False, sharex=False)
    diff=quotient_times
    ax1.plot(diff, quotient, ".", label=protname, color="blue")
    ax1.set_ylim(0, 1.0001)
    ax1.set_title(protname)
    ax1.set_xlabel("quotient_times")
    ax1.set_ylabel("quotient")
    ax1.legend()

    sns.distplot(quotient, hist=True, label=protname, ax=ax2, rug=True)
    ax2.set_title('basic distplot (kde=True)')

    # taken from seaborn's source code (utils.py and distributions.py)
    def seaborn_kde_support(data, bw, gridsize, cut, clip):
        if clip is None:
            clip = (-np.inf, np.inf)
        support_min = max(data.min() - bw * cut, clip[0])
        support_max = min(data.max() + bw * cut, clip[1])
        return np.linspace(support_min, support_max, gridsize)

    kde_estim = stats.gaussian_kde(quotient, bw_method='scott')

    # manual linearization of data
    #linearized = np.linspace(quotient.min(), quotient.max(), num=500)

    # or better: mimic seaborn's internal stuff
    bw = kde_estim.scotts_factor() * np.std(quotient)
    linearized = seaborn_kde_support(quotient, bw, 100, 3, None)

    # computes values of the estimated function on the estimated linearized inputs
    Z = kde_estim.evaluate(linearized)

    # https://stackoverflow.com/questions/29661574/normalize-numpy-array-columns-in-python
    def normalize(x):
        return (x - x.min(0)) / x.ptp(0)

    # normalize so it is between 0;1
    Z2 = normalize(Z)
    for name, func in {'min': np.min, 'max': np.max}.items():
        print('{}: source={}, normalized={}'.format(name, func(Z), func(Z2)))

    # plot is different from seaborns because not exact same method applied
    ax3.plot(linearized, Z, ".", label=protname, color="orange")
    ax3.set_title('Non linearized gaussian kde values')

    # manual kde result with Y axis avalues normalized (between 0;1)
    ax4.plot(linearized, Z2, ".", label=protname, color="green")
    ax4.set_title('Normalized gaussian kde values')

    plt.show()

Выход:

System versions          : 3.7.2 (default, Feb 21 2019, 17:35:59) [MSC v.1915 64 bit (AMD64)]
System versions          : sys.version_info(major=3, minor=7, micro=2, releaselevel='final', serial=0)
Numpy versqion           : 1.16.2
matplotlib.pyplot version: 3.0.2
seaborn version          : 0.9.0
min: source=0.0021601491646143518, normalized=0.0
max: source=9.67319154426489, normalized=1.0

Вопреки комментарию, сюжет:

[(x-min(quotient))/(max(quotient)-min(quotient)) for x in quotient]

Не меняет поведение! Это только изменяет исходные данные для оценки плотности ядра. Форма кривой останется прежней.

Цитирование документа Морского Дорог :

Эта функция сочетает в себе функцию исторических значений matplotlib (с вычисление правильного размера ячейки по умолчанию) с помощью морской волны kdeplot () и Функции rugplot (). Он также может соответствовать дистрибутивам scipy.stats и нанесите приблизительный PDF на данные.

По умолчанию:

kde: bool, необязательно для True Следует ли строить оценку плотности ядра по Гауссу.

По умолчанию используется kde. Цитируя документ Морского Корадо:

Подгонка и построение одномерной или двумерной оценки плотности ядра.

Цитирование Метод гауссовского kde SCiPy doc :

Представление оценки плотности ядра с использованием гауссовых ядер.

Оценка плотности ядра - это способ оценки плотности вероятности функция (PDF) случайной величины непараметрическим способом. gaussian_kde работает как с переменными, так и с переменными данными. Это включает в себя автоматическое определение пропускной способности. Оценка работает лучше всего для унимодального распространения; бимодальные или мультимодальные распределения имеют тенденцию быть слишком спокойным.

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

Вот пример с различными законами:

import numpy as np
from scipy.stats import uniform, powerlaw, logistic
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import sys

print('System versions          : {}'.format(sys.version))
print('System versions          : {}'.format(sys.version_info))
print('Numpy versqion           : {}'.format(np.__version__))
print('matplotlib.pyplot version: {}'.format(matplotlib.__version__))
print('seaborn version          : {}'.format(sns.__version__))

protocols = {}

types = {"data_v": "data_v.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }
    fig, [(ax1, ax2, ax3), (ax4, ax5, ax6)] = plt.subplots(2,3, sharey=False, sharex=False)
    diff=quotient_times
    ax1.plot(diff, quotient, ".", label=protname, color="blue")
    ax1.set_ylim(0, 1.0001)
    ax1.set_title(protname)
    ax1.set_xlabel("quotient_times")
    ax1.set_ylabel("quotient")
    ax1.legend()
    quotient2 = [(x-min(quotient))/(max(quotient)-min(quotient)) for x in quotient]
    print(quotient2)
    sns.distplot(quotient, hist=True, label=protname, ax=ax2, rug=True)
    ax2.set_title('basic distplot (kde=True)')
    sns.distplot(quotient2, hist=True, label=protname, ax=ax3, rug=True)
    ax3.set_title('logistic distplot')

    sns.distplot(quotient, hist=True, label=protname, ax=ax4, rug=True, kde=False, fit=uniform)
    ax4.set_title('uniform distplot')
    sns.distplot(quotient, hist=True, label=protname, ax=ax5, rug=True, kde=False, fit=powerlaw)
    ax5.set_title('powerlaw distplot')
    sns.distplot(quotient, hist=True, label=protname, ax=ax6, rug=True, kde=False, fit=logistic)
    ax6.set_title('logistic distplot')
    plt.show()

Выход:

System versions          : 3.7.2 (default, Feb 21 2019, 17:35:59) [MSC v.1915 64 bit (AMD64)]
System versions          : sys.version_info(major=3, minor=7, micro=2, releaselevel='final', serial=0)
Numpy versqion           : 1.16.2
matplotlib.pyplot version: 3.0.2
seaborn version          : 0.9.0
[1.0, 0.05230125523012544, 0.0433775382360589, 0.024590765616971128, 0.05230125523012544, 0.05230125523012544, 0.05230125523012544, 0.02836946874603772, 0.05230125523012544, 0.05230125523012544, 0.05230125523012544, 0.05230125523012544, 0.03393500048652319, 0.05230125523012544, 0.05230125523012544, 0.05230125523012544, 0.0037013196009011043, 0.0, 0.05230125523012544]

Скриншот:

enter image description here

...