【问题标题】:Max of 99percentile in a window of list of lists列表列表窗口中最多 99 个百分位
【发布时间】:2018-10-26 12:26:36
【问题描述】:

我有一个列表列表(2000x1000),但作为示例考虑这个(10x3):

l = [[8, 7, 6], [5, 3, 1], [4, 5, 9], [1, 5, 1], [3, 5, 7], [8, 2, 5], [1, 9, 2], [8, 7, 6], [9, 9, 9], [4, 5, 9]] 

在此示例中,每个列表对应于每个瞬间的 3 个测量值:

t0 -> [8,7,6]

t1 -> [5,3,1] 等等。

我想将测量值与位置的 4 个瞬间窗口进行比较,并取最大值,即峰值到峰值的 99 个百分位数。

示例

让我们考虑第一个窗口:

[8, 7, 6], [5, 3, 1], [4, 5, 9], [1, 5, 1] :
[8,5,4,1] -> peak to peak: 8-1=7
[7,3,5,5] -> ptp=4
[6,1,9,1] -> ptp=8

使用这 3 个值 [7,4,8] 我想取 99percentile 中的最大值,在本例中为 7

对于第二个窗口:

[5, 3, 1], [4, 5, 9], [1, 5, 1], [3, 5, 7]:
[5,4,1,3] -> ptp=4
[3,5,5,5] -> ptp=2
[1,9,1,7] -> ptp=8

最大 99% -> 4 在对所有大小为 4 的窗口执行此操作后,我想用这些值创建一个列表。

我的代码是下面这个,但它很慢。有没有一种快速的方法来实现这一点?

注意:我不能使用 pandas,Numpy 版本应该是
num_meas = 4
m = []
for index, i in enumerate(l):
    if index < len(l) - num_meas + 1:
        p = []
        for j in range(len(i)):
            t = []
            for k in range(num_meas):
                t.append(l[index + k][j])
            t = [x for x in t if ~np.isnan(x)]
            try:
                a = np.ptp(t)
            except ValueError:
                a = 0
            p.append(a)
        perce = np.percentile(p, 99)
        p = max([el for el in p if el < perce])
        m.append(p)
print m

输出:

[7, 4, 7, 6, 5, 7, 7]

【问题讨论】:

  • 2000x1000,例子是10x3
  • 这是否意味着你可以使用 numpy>1.6 ?
  • 不,必须是 1.6 或之前的版本
  • 峰到峰的例子有个小错误,[7,3,5,9] -> ptp=6 应该是 [7,3,5,5] -> ptp=4
  • 谢谢,你是对的

标签: python python-2.7 list numpy


【解决方案1】:

请检查以下代码是否适用于 NumPy 1.6:

import numpy as np

l = [[8, 7, 6], [5, 3, 1], [4, 5, 9], [1, 5, 1], [3, 5, 7], [8, 2, 5],
     [1, 9, 2], [8, 7, 6], [9, 9, 9], [4, 5, 9]]

l = np.array(l)

# range matrix
mat_ptp = np.zeros((l.shape[0]-3, l.shape[1]))

for i in range(l.shape[0]-3):
    l[i:i+4].ptp(axis=0, out=mat_ptp[i])

percentiles = np.percentile(mat_ptp, 99, axis=1)
greater_pos = np.greater_equal(mat_ptp, percentiles.reshape(-1, 1))
mat_ptp[greater_pos] = -np.inf

result = np.max(mat_ptp, axis=1)

为了提高性能,您可以尝试使用 numpy.它可能比使用for 循环和append 函数快得多。

编辑

抱歉,我没有注意到您希望所选元素严格小于百分位数。这是正确的版本。

基准

只是为了验证有关性能的问题,结果如下:

l = np.random.randint(0, 100, size=(200, 100))

使用timeit 运行 100 次:

OP code: 0.5197743272900698 ms in average
Code above: 0.0021439407201251015 in average

【讨论】:

  • 感谢您的回答,该方法似乎更快更容易,但输出错误。对于我发布的示例,它给出:[7 4 7 7 7 7]
  • @Joe 抱歉,我没有注意到您希望所选元素严格小于百分位数。我刚刚编辑了我的答案。
  • 如果我有nan,我想在百分位数和最大值中忽略它们,我该怎么办?
  • @Joe 好吧,这真的取决于你想用NaNs 做什么。在大多数情况下,我会在预处理过程中消除它们,因为在操作过程中一直处理它们会很混乱。我会简单地做l[np.isnan(l)] = a_value。但是如何选择a_value 是具体问题。在您的情况下,np.ptp 不会忽略 NaN。所以如果你在计算百分位数时不考虑NaN,你可以留下它,最后使用np.nanmax。附:使用Numpy&gt;=1.9,您也可以使用np.nanpercentile。所以我建议你继续使用最新的 numpy 版本。
猜你喜欢
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多