给定一个元素列表( [1,27,10,...] ),我需要生成每个元素的n重复列表,如‘1,1,.,1,27,27,.,27,10,.,10’。
做这件事最优雅、最浪漫、最快捷的方法是什么?
答案
numpy是最快、最简洁的解决方案。
np.repeat(my_list, n)看上去很像pythonic (归功于B.M.),而扁平化的numpy数组看起来要快得多。
还请看一下B.M.的文章中的numba alternative
更详细的
我测试了三种方法:一是双循环,二是带有索引功能的单循环;三是扁平numpy数组。(编辑:迈克使用extend__的第4种方法,B.M.使用np.repeat的第5种方法,gsb-eng的第6种方法理解,第7种方法迭代工具)
令人惊讶的是,我发现扁平数组是,是我的机器上在python2.7中最快的方法。但是,在某些机器和Python 3中,您可能需要测试迭代工具和理解。您可以复制/粘贴下面的Python2代码以进行快速检查,排序后的timeit结果如下:
Flattened array: 8.8ms
Numpy Repeat: 10.87ms
Extend List: 14.37ms
Itertools Repeat: 14.91ms
Itertools Chain Comprehension: 18.72ms
Itertools Chain: 18.73ms
Double Loop : 58.4ms
Single Loop + index by division: 251.29ms
Double Loop + comprehension: 255.76ms这是生成结果的代码:
import numpy as np
import timeit
n = 100
my_list = range(10)
n_elements = len(my_list)
# === Double Loop =============================================================
def double_loop():
my_long_list = []
for list_element in my_list:
my_long_list += [list_element] * n
return my_long_list
# === Double Loop with Comprehension =========================================================
def double_loop_comp():
# List comprehension
return [i for i in my_list for j in xrange(n)]
# === Single Loop with Indexing Function ======================================
def one_loop_with_indexing():
my_long_list = []
for i in range(n*n_elements):
my_long_list.append(my_list[i // n])
return my_long_list
# === Flattened Array =========================================================
def flattened_array():
my_array = np.zeros([n_elements, n])
for i in range(n_elements):
my_array[i,:] = my_list[i]
return my_array.flatten()
# === Extend List =========================================================
def extend_list():
my_long_list = []
for list_element in my_list:
my_long_list.extend([list_element] * n)
return my_long_list
# === Numpy Repeat =========================================================
def numpy_repeat():
return np.repeat(my_list, n)
# === Itertools Repeat ========================================================
def iter_repeat():
my_long_list = []
for x in my_list:
my_long_list.extend( itertools.repeat(x,n) )
return my_long_list
# === Itertools Chain =========================================================
def iter_chain():
return list( itertools.chain.from_iterable( itertools.repeat(x,n) for x in my_list ) )
# === Itertools Chain Comp ====================================================
def iter_chain_comp():
return list( itertools.chain.from_iterable( [itertools.repeat(x,n) for x in my_list] ) )
time_double_loop = timeit.timeit(double_loop, number=1000)
time_double_loop_comp = timeit.timeit(double_loop_comp, number=1000)
time_single_loop = timeit.timeit(one_loop_with_indexing, number=1000)
time_flattened_array = timeit.timeit(flattened_array, number=1000)
time_extend_list = timeit.timeit(extend_list, number=1000)
time_np_repeat = timeit.timeit(numpy_repeat, number=1000)
time_it_repeat = timeit.timeit(iter_repeat, number=1000)
time_it_chain = timeit.timeit(iter_chain, number=1000)
time_it_chain_comp = timeit.timeit(iter_chain_comp, number=1000)
print 'Double Loop : ' + str(round(time_double_loop*1000,2))+'ms'
print 'Double Loop + comprehension: ' + str(round(time_double_loop_comp*1000,2))+'ms'
print 'Single Loop + index by division: ' + str(round(time_single_loop*1000,2))+'ms'
print 'Flattened array: ' + str(round(time_flattened_array*1000,2))+'ms'
print 'Extend List: ' + str(round(time_extend_list*1000,2))+'ms'
print 'Numpy Repeat: ' + str(round(time_np_repeat*1000,2))+'ms'
print 'Itertools Repeat: ' + str(round(time_it_repeat*1000,2))+'ms'
print 'Itertools Chain: ' + str(round(time_it_chain*1000,2))+'ms'
print 'Itertools Chain Comprehension: ' + str(round(time_it_chain_comp*1000,2))+'ms'发布于 2016-02-06 14:45:18
在fast类别中,使用a=np.array(my_list) (测试中的100个元素):
可读性:
In [12]: %timeit np.repeat(a,100)
10000 loops, best of 3: 80.4 µs per loop棘手的:
In [13]: %timeit np.lib.stride_tricks.as_strided(a,(100,100),(a.itemsize,0)).ravel()
10000 loops, best of 3: 29.5 µs per loop与numba的及时对比(conda install numba后)
from numba import jit
@jit
def numbarep(a,n):
res=np.empty(a.size*n,dtype=a.dtype)
offset=0
for e in a:
for k in range(offset,offset+n):
res[k]=e
offset+=n
return res
In [14]: %timeit numbarep(a,100)
100000 loops, best of 3: 14.8 µs per loop https://stackoverflow.com/questions/35240074
复制相似问题