值之间的数组百分比

Nil*_*ujo 5 python numpy scipy pandas

我正在寻找一种简单的方法,使用python在一定的时间间隔内找到数据的百分比.

考虑浮点值的数组X. 我想做类似于分位数的事情:

X.quantile(np.linspace(0,1,11))
Run Code Online (Sandbox Code Playgroud)

但相反,我想知道例如,哪个百分比的值在-10和10之内.

X.method([-10,10])
Run Code Online (Sandbox Code Playgroud)

我知道我可以做到这一点scipy.stats.percentileofscore

percentileofscore(X,10) - percentileofscore(X,-10)
Run Code Online (Sandbox Code Playgroud)

我想知道是否有一个更简单,实施的解决方案,所以我可以做

X.method([a,b,c])
Run Code Online (Sandbox Code Playgroud)

这将使我之间值的百分比min(X)a,ab, bc,终于之间cmax(X)

小智 5

一个简单的解决方案是使用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])
Run Code Online (Sandbox Code Playgroud)


tel*_*tel 5

基本的 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
Run Code Online (Sandbox Code Playgroud)

输出:

0.666
Run Code Online (Sandbox Code Playgroud)

如果你愿意使用 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
Run Code Online (Sandbox Code Playgroud)

输出:

0.666
Run Code Online (Sandbox Code Playgroud)

陷阱

每个区间分析方法都涉及您正在考虑的区间的显式或隐式定义。两端的区间是否闭合(即包括极值),例如[-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)
Run Code Online (Sandbox Code Playgroud)

输出:

0.6129032258064516
0.6774193548387096
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

输出:

0.6774193548387096
0.6774193548387096
Run Code Online (Sandbox Code Playgroud)

所有这一切都是为了说:当您为这种区间分析选择一种方法时,请注意它的边界约定,并在所有相关分析中使用一致的约定。

其他解决方案

如果您假设数据已排序(或者您自己排序),则可以使用np.searchsorted

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

输出:

0.65
Run Code Online (Sandbox Code Playgroud)


Nil*_*ujo 1

只是为了让你们知道我找到了一个非常简单的解决方案,使用value_countsnp.inf

import pandas as pd
import numpy as np

values = pd.Series(np.linspace(0, 100, 200))
values.value_counts(normalize=True, sort=False, bins=[-np.inf, 10, 20, np.inf])
Run Code Online (Sandbox Code Playgroud)

normalize=True返回百分比,将其设置为 False 给出计数

sort=False将按 bin 的顺序返回,将其设置为 True 将按计数的降序值排序

bins定义间隔点

这返回

(-inf, 10.0]    0.1
(10.0, 20.0]    0.1
(20.0, inf]     0.8
dtype: float64
Run Code Online (Sandbox Code Playgroud)