Процент массива между значениями - PullRequest
0 голосов
/ 17 декабря 2018

Я ищу простой способ выяснить, какой процент данных находится в определенных интервалах, используя python.

Рассмотрим массив X значений с плавающей запятой.Я хотел бы сделать что-то похожее на квантили:

X.quantile(np.linspace(0,1,11))

Но вместо этого я хотел бы знать, какой процент значений находится в пределах -10 и 10, например.

X.method([-10,10])

Я знаю, что могу сделать это с scipy.stats.percentileofscore, делая

percentileofscore(X,10) - percentileofscore(X,-10)

Мне было интересно, есть ли более простое, реализованное решение, чтобы я мог вместо этого сделать

X.method([a,b,c])

Что дало бы мнепроцент значений между min(X) и a, a и b, b и c и, наконец, между c и max(X)

Ответы [ 3 ]

0 голосов
/ 17 декабря 2018

Базовые решения Numpy и Pandas

Нет полностью упакованного метода (в Numpy), но есть много однотипных лайнеров.Вот как это сделать, используя сравнение и логические операции ( Редактировать подсказку Полу Панцеру за предложение использовать np.count_nonzero):

import numpy as np

arr = np.linspace(-15,15,1000)
np.count_nonzero((arr > -10) & (arr < 10))/arr.size

Вывод:

0.666

Если вы хотите использовать Pandas, метод pandas.Series.between немного приблизит вас к необходимому пакету:

import pandas as pd

sr = pd.Series(np.linspace(-15,15,1000))
np.count_nonzero(sr.between(-10,10))/sr.size

Вывод:

0.666

Подводные камни

Каждый метод анализа интервалов включает в себя явное или неявное определение рассматриваемого интервала.Является ли интервал закрытым (т.е. включает в себя экстремальные значения) на обоих концах, как [-10, 10]?Или это полуоткрытое (то есть исключает крайнее значение на одном конце), как [-10, 10)?И т. Д.

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

arr = np.arange(-15,16)
print(np.count_nonzero((arr > -10) & (arr < 10))/arr.size)
print(np.count_nonzero(pd.Series(arr).between(-10,10))/arr.size)

Выходные данные:

0.6129032258064516
0.6774193548387096

По умолчанию используется метод pd.Series.betweenк закрытому интервалу на обоих концах, поэтому для сопоставления с ним в Numpy вам придется использовать операторы инклюзивного сравнения:

arr = np.arange(-15,16)
print(np.count_nonzero((arr >= -10) & (arr <= 10))/arr.size)
print(np.count_nonzero(pd.Series(arr).between(-10,10))/arr.size)

Вывод:

0.6774193548387096
0.6774193548387096

Все это дляскажем: когда вы выбираете метод для этого вида интервального анализа, помните о его границах и применяйте согласованные соглашения во всех связанных анализах.

Другие решения

Если вы предполагаетеданные сортируются (или если вы сортируете их самостоятельно), вы можете использовать np.searchsorted:

arr = np.random.uniform(-15,15,100)
arr.sort()
np.diff(arr.searchsorted([-10, 10]))[0]/arr.size

Вывод:

0.65
0 голосов
/ 18 декабря 2018

Настройка

a = np.linspace(-15,15,1000)

Встроенного метода не существует, но довольно просто определить свой собственный, используя np.count_nonzero и size.В общем:

c = (a > -10) & (a < 10)
np.count_nonzero(c) / a.size

Вы можете обернуть это в функцию для удобства и учета случаев, когда вам нужны закрытые интервалы:

def percent_between(a, lower, upper, closed_left=False, closed_right=False):
    """
    Finds the percentage of values between a range for a numpy array

    Parameters
    ----------
    a: np.ndarray
      numpy array to calculate percentage
    lower: int, float
      lower bound
    upper: int, float
      upper bound
    closed_left:
      closed left bound ( > vs >= )
    closed_right:
      closed right bound ( < vs <= )
    """
    l = np.greater if not closed_left else np.greater_equal
    r = np.less if not closed_right else np.less_equal

    c = l(a, lower) & r(a, upper)
    return np.count_nonzero(c) / a.size

percent_between(a, -10, 10)

0.666
0 голосов
/ 17 декабря 2018

Простым решением является использование np.histogram:

import numpy as np
X = np.arange(20)
values = [5, 13]  # these are your a and b
freq = np.histogram(X, bins=[-np.inf] + values + [np.inf])[0]/X.size
print(freq)
>> array([0.25, 0.4 , 0.35])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...