值之间的数组百分比

时间:2018-12-17 20:18:58

标签: python pandas numpy scipy

我正在寻找一种简单的方法来使用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)aabbc之间的值的百分比,以及最后在cmax(X)

之间

4 个答案:

答案 0 :(得分:4)

基本的Numpy和Pandas解决方案

没有完全预先包装的方法(在Numpy中),但是有很多衬板。以下是使用比较操作和逻辑操作(Paul Panzer的编辑提示建议使用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 method可使您更接近所需的完整软件包:

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值的数组时,这往往不是问题(因为不太可能有任何数据完全落入极端),但是在处理{ {1}}。例如,如果数组包含间隔的边界值,则我上面列出的两种方法可以给出不同的结果:

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 方法默认为两端封闭的时间间隔,因此要在Numpy中进行匹配,您必须使用包含性比较运算符:

pd.Series.between

输出:

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

答案 1 :(得分:3)

一个简单的解决方案是使用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])

答案 2 :(得分:1)

设置

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

不存在内置方法,但是使用np.count_nonzerosize定义自己的方法非常简单。一般来说:

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

答案 3 :(得分:0)

我现在要提到的另一种解决方案是将熊猫cutvalue_countsnp.inf

import pandas as pd
import numpy as np

values = pd.Series(np.linspace(0, 100, 200))
bins = [-np.inf, 10, 20, np.inf]
cutted = pd.cut(values, bins)
cutted.value_counts(normalize=True, sort=False)

pd.cut将每个值分配给一个容器,value_counts将对出现的次数进行计数,normalize=True将给出百分比而不是实际计数,并且sort=False将保持容器的顺序在pd.cut中使用。 sort=True将按照频率对垃圾箱进行排序

(-inf, 10.0]    0.1
(10.0, 20.0]    0.1
(20.0, inf]     0.8