【问题标题】:python numpy mask mean performancepython numpy掩码平均性能
【发布时间】:2015-03-15 16:23:28
【问题描述】:

好的,经过一番搜索,我似乎找不到直接解决此问题的 SO 问题。我研究了蒙面数组,虽然它们看起来很酷,但我不确定它们是否是我需要的。

考虑 2 个 numpy 数组:

zone_data 是一个二维 numpy 数组,其中包含具有相同值的元素块。这是我的“区域”。

value_data 是一个具有任意值的二维 numpy 数组(zone_data 的精确形状)。

我寻找一个与 zone_data/value_data 形状相同的 numpy 数组,其中包含每个区域的平均值来代替区域编号。

示例...以 ascii 艺术形式。

zone_data(4 个不同的区域):

1, 1, 2, 2
1, 1, 2, 2
3, 3, 4, 4
3, 4, 4, 4

value_data:

1, 2, 3, 6
3, 0, 2, 5
1, 1, 1, 0
2, 4, 2, 1

我的结果,叫它result_data

1.5, 1.5, 4.0, 4.0
1.5, 1.5, 4.0, 4.0
2.0, 2.0, 1.0, 1.0
2.0, 2.0, 1.0, 1.0

这是我的代码。只要给我一个完美的结果,它就可以正常工作。

result_data = np.zeros(zone_data.shape)
for i in np.unique(zone_data):
    result_data[zone_data == i] = np.mean(value_data[zone_data == i])

我的数组很大,我的代码 sn-p 需要几秒钟。我认为我有知识差距,没有找到任何有用的东西。循环方面需要委托给库或其他东西...aarg!

我寻求帮助以使其更快!蟒蛇大神,求你的智慧!

编辑——添加基准脚本

import numpy as np
import time

zones = np.random.randint(1000, size=(2000,1000))
values = np.random.rand(2000,1000)

print 'start method 1:'
start_time = time.time()

result_data = np.zeros(zones.shape)
for i in np.unique(zones):
    result_data[zones == i] = np.mean(values[zones == i])

print 'done method 1 in %.2f seconds' % (time.time() - start_time)

print
print 'start method 2:'
start_time = time.time()

#your method here!

print 'done method 2 in %.2f seconds' % (time.time() - start_time)

我的输出:

start method 1:
done method 1 in 4.34 seconds

start method 2:
done method 2 in 0.00 seconds

【问题讨论】:

    标签: python arrays performance numpy masking


    【解决方案1】:

    你可以使用np.bincount:

    count = np.bincount(zones.flat)
    tot = np.bincount(zones.flat, weights=values.flat)
    avg = tot/count
    result_data2 = avg[zones]
    

    这给了我

    start method 1:
    done method 1 in 3.13 seconds
    
    start method 2:
    done method 2 in 0.01 seconds
    >>> 
    >>> np.allclose(result_data, result_data2)
    True
    

    【讨论】:

    • 出色地使用了bincount。 +1
    • DSM,太棒了!我之所以喜欢 SO 主要是因为像你这样的人可以分享一些我需要很长时间才能找到自己的具体知识。太感谢了!这不仅仅是一个简单的练习......这将打开我在应用程序中的一个瓶颈。也喜欢“np.allclose”......真是个宝石。
    【解决方案2】:

    我以为我在 scipy 的某个地方看到过这个,但我再也找不到了。你看过那里吗?

    无论如何,你可以通过改变你的循环来获得第一个改进:

    result_data = np.empty(zones.shape)  # minor speed gain
    for label in np.unique(zones):
        mask = zones==label
        result_data[mask] = np.mean(values[mask])
    

    这样您就不必进行两次布尔比较。这会减少一点执行时间。

    【讨论】:

    • 这是一个很好的观察。在我的情况下,它可以节省大约 40%...这很好,我应该知道得更好...我在许多其他地方都这样做过。我会接受 DSM 的答案,但它的速度要快 100 倍以上!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 2021-05-20
    相关资源
    最近更新 更多