有条件计算python数组不同元素的平均值的最快方法是什么?

时间:2018-07-27 13:45:22

标签: python numpy

下面的Python代码大约执行2 secC中的等效代码在6 ms中执行。

一些解释:我有2个ADC通道的串行数据(adc0adc1adc0adc1,...)。 如果adc1 <= 10必须将adc1加到总数上,否则必须加上adc0。这些值乘以不同的系数(0.10.01)。

#!/usr/bin/env python
import time
import numpy as np 

dd = np.random.randint(0, 20, size=(2*1000*1000))

t_start = time.clock()

avg_sum1 = 0.0
BlockOffset = 0     
while BlockOffset < len(dd):
    if dd[BlockOffset + 1] <= 10:
        avg_sum1 += dd[BlockOffset + 1] * 0.1
    else:
        avg_sum1 += dd[BlockOffset + 0] * 0.01
    BlockOffset += 2

print('Avg: ' + str(avg_sum1 / len(dd) / 2))    
print('Exe time: ' + str(time.clock() - t_start))

使用内置函数或numpy最快的方法是什么?

2 个答案:

答案 0 :(得分:1)

首先,您需要确定平均计算(运算符优先级):

avg_sum1 / (len(dd) / 2)  # or avg_sum1 / len(dd) * 2

Out[]:
0.31740819000001924
2.8 s ± 28.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

您可以在numpy中执行此操作,例如:

In []:
np.where(dd[1::2] <= 10, dd[1::2]*0.1, dd[0::2]*0.01).mean()

Out[]:
0.31740818999999987
10.8 ms ± 61.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

答案 1 :(得分:-1)

有很多方法可以加快速度。这是使用pandas的解决方案(也许也可以仅使用numpy来完成)。

在此代码中,f1()是您的原始功能,而f2()使用的是pandas

import numpy as np
import pandas as pd
import time

def f1(data):
    t_start = time.perf_counter()

    offset = 0
    sum_1 = 0.0
    while offset < data.shape[0]:
        if data[offset + 1] <= 10:
            sum_1 += data[offset + 1] * 0.1
        else:
            sum_1 += data[offset + 0] * 0.01
        offset += 2
    n = data.shape[0] / 2
    avg_1 = sum_1 / n

    t_end = time.perf_counter()

    return {
        'calc_time': t_end - t_start,
        'n': n,
        'sum': sum_1,
        'avg': avg_1,
    }

def f2(data):
    t_start = time.perf_counter()

    df = pd.DataFrame()
    df['adc0'] = data[0::2]     # every second element, starting at 0
    df['adc1'] = data[1::2]     # every second element, starting at 1

    df['sum_value'] = np.where(
        df['adc1'] <= 10,
        df['adc1'] * 0.1,
        df['adc0'] * 0.01)
    sum_1 = df['sum_value'].sum()
    n = df.shape[0]
    avg_1 = sum_1 / n

    t_end = time.perf_counter()

    return {
        'calc_time': t_end - t_start,
        'n': n,
        'sum': sum_1,
        'avg': avg_1,
    }

if __name__ == '__main__':
    numbers = np.random.randint(0, 20, size=(2*1000*1000))

    r = f1(numbers)
    print(r)
    r = f2(numbers)
    print(r)

此代码显示f2()的速度更快,大约使用123 ms(不到f1()时间的10%)。

# f1
{'avg': 0.31791369000003045, 'n': 1000000.0, 'sum': 317913.69000003044,
 'calc_time': 4.765112441743648}
# f2
{'avg': 0.31791368999999986, 'n': 1000000, 'sum': 317913.68999999989,
 'calc_time': 0.12356162259120662}

肥胖:我假设两个函数之间的sumavg之差源自浮点精度的处理方式,但我不确定。 您需要为用例考虑多少个小数位?这个小的差异重要吗?