我正在寻找一种简单的方法来使用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)
答案 0 :(得分:4)
没有完全预先包装的方法(在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_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
答案 3 :(得分:0)
我现在要提到的另一种解决方案是将熊猫cut
与value_counts
和np.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