【问题标题】:Percentage of array between values值之间的数组百分比
【发布时间】:2019-05-18 05:53:21
【问题描述】:

我正在寻找一种简单的方法来使用 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) 之间的值的百分比

【问题讨论】:

  • 不,对此没有预编码的解决方案。您发布的内容正是它的完成方式。如果您经常需要它,只需将其包装在一个函数中即可。
  • 您是在寻找预定义的方法还是愿意自己编写一个?

标签: python pandas numpy scipy


【解决方案1】:

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

    基本的 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 值数组时,这往往不是问题(因为任何数据都不太可能完全处于极端),但在处理 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
    

    【讨论】:

    • 我什至不包括需要排序数据的方法。即使对数据进行了排序,它也比其他方法慢得多。如果数据没有排序,它只会引入不必要的时间复杂度,O(n) vs O(nlogn)
    • searchsorted 不是该解决方案时间复杂度的限制因素。
    • "searchsorted is not what bounds..." 你的意思是在未排序的情况下,对吧?在排序的情况下,至少理论上应该是O(log(n))。如果不是,你能解释一下你的意思吗?
    【解决方案3】:

    设置

    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
    

    【讨论】:

    【解决方案4】:

    只是想让你们知道,我使用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])
    

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多