最快的创造方式np.阵列对于元组列表中的每个项

2024-06-24 12:28:34 发布

您现在位置:Python中文网/ 问答频道 /正文

有一个元组列表l = [(x,y,z), (x,y,z), (x,y,z)] 我们的想法是找到最快的方法来创造不同的np.阵列对于每个x-s,y-s,z-s。需要帮助找到最快的解决方案。为了进行速度比较,我使用下面附带的代码

import time

def myfast():
   code

n = 1000000
t0 = time.time()
for i in range(n): myfast()
t1 = time.time()

total_n = t1-t0

1.  np.array([i[0] for i in l])
    np.array([i[1] for i in l])
    np.array([i[2] for i in l])

output: 0.9980638027191162

2.  array_x = np.zeros((len(l), 1), dtype="float")
    array_y  = np.zeros((len(l), 1), dtype="float")
    array_z  = np.zeros((len(l), 1), dtype="float")

    for i, zxc in enumerate(l):
        array_x[i] = zxc[0]
        array_y[i] = zxc[1]
        array_z[i] = zxc[2]

output 5.5509934425354

3. [np.array(x) for x in zip(*l)]

output 2.5070037841796875

5. array_x, array_y, array_z = np.array(list(zip(*l)))

output 2.725318431854248


Tags: inforoutputlentimenpzeroszip
3条回答

你可以试试:

import numpy
array_x, array_y, array_z = numpy.array(list(zip(*l)))

或者只是:

numpy.array(list(zip(*l)))

更优雅的方式:

numpy.array(l).transpose()

这里有一些非常好的选择,所以我总结了它们并比较了速度:

import numpy as np

def f1(input_data):
    array_x = np.array([elem[0] for elem in input_data])
    array_y = np.array([elem[1] for elem in input_data])
    array_z = np.array([elem[2] for elem in input_data])

    return array_x, array_y, array_z

def f2(input_data):
    array_x = np.zeros((len(input_data), ), dtype="float")
    array_y = np.zeros((len(input_data), ), dtype="float")
    array_z = np.zeros((len(input_data), ), dtype="float")

    for i, elem in enumerate(input_data):
        array_x[i] = elem[0]
        array_y[i] = elem[1]
        array_z[i] = elem[2]

    return array_x, array_y, array_z

def f3(input_data):
    return [np.array(elem) for elem in zip(*input_data)]

def f4(input_data):
    return np.array(list(zip(*input_data)))

def f5(input_data):
    return np.array(input_data).transpose()

def f6(input_data):
    array_all = np.array(input_data)
    array_x = array_all[:, 0]
    array_y = array_all[:, 1]
    array_z = array_all[:, 2]

    return array_x, array_y, array_z

首先,我断言它们都返回相同的数据(使用np.array_equal()):

data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
for array_list in zip(f1(data), f2(data), f3(data), f4(data), f5(data), f6(data)):
    # print()
    # for i, arr in enumerate(array_list):
    #     print('array from function', i+1)
    #     print(arr)
    for i, arr in enumerate(array_list[:-1]):
        assert np.array_equal(arr, array_list[i+1])

时间比较:

import timeit
for f in [f1, f2, f3, f4, f5, f6]:
    t = timeit.timeit('f(data)', 'from __main__ import data, f', number=100000)
    print('{:5s} {:10.4f} seconds'.format(f.__name__, t))

给出以下结果:

data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]    # 3 tuples
timeit number=100000
f1        0.3184 seconds
f2        0.4013 seconds
f3        0.2826 seconds
f4        0.2091 seconds
f5        0.1732 seconds
f6        0.2159 seconds

data = [(1, 2, 3) for _ in range(10**6)]    # 1 millon tuples
timeit number=10
f1        2.2168 seconds
f2        2.8657 seconds
f3        2.0150 seconds
f4        1.9790 seconds
f5        2.6380 seconds
f6        2.6586 seconds

使f5()成为短输入的最快选项,f4()成为大输入的最快选项。你知道吗


如果每个元组中的元素数超过3个,则只有3个函数适用于该情况(其他函数针对每个元组中的3个元素进行硬编码):

data = [tuple(range(10**4)) for _ in range(10**3)]
timeit number=10
f3       11.8396 seconds
f4       13.4672 seconds
f5        4.6251 seconds

使f5()再次成为这些标准的最快选项。你知道吗

也许我遗漏了什么,但为什么不直接将元组列表传递给np.array?说如果:

n = 100
l = [(0, 1, 2) for _ in range(n)]

arr = np.array(l)
x = arr[:, 0]
y = arr[:, 1]
z = arr[:, 2]

顺便说一句,我更喜欢使用以下时间代码:

from timeit import default_timer as timer

t0 = timer()
do_heavy_calculation()
print("Time taken [sec]:", timer() - t0)

相关问题 更多 >