我目前正在尝试找出在循环中创建numpy数组的最有效方法,以下是示例:
import numpy as np
from time import time
tic = time()
my_list = range(1000000)
a = np.zeros((len(my_list),))
for i in my_list:
a[i] = i
toc = time()
print(toc-tic)
VS
tic = time()
a = []
my_list = range(1000000)
for i in my_list:
a.append(i)
a = np.array(a)
toc = time()
print(toc-tic)
我期待第二个比第一个慢得多,因为在for循环的每个步骤都需要新的内存,但是这些大致相同而且我想知道为什么,但仅仅是为了好奇因为我可以用它们做到这一点。
我实际上想要编写一个简单的numpy数组,其中包含从数据框中提取的数据,它看起来非常混乱。我想知道是否会有更多的pythonic方式来做到这一点。我有这个数据框和我需要的标签列表,最简单的想法是执行以下操作(我需要的值是每列的最后一个):
vars_outputs = ["x1", "x2", "ratio_x1_x2"]
my_df = pd.read_excel(path)
outpts = np.array(my_df[vars_outputs][-1])
然而,这是不可能的,因为我想要的一些标签在数据帧中不能直接使用:例如,需要从两个第一列计算ratio_x1_x2。所以我添加了一个带有缺失标签的dict以及计算它们的方式(它唯一的比例):
missing_labels = {"ratio_x1_x2" : ["x1", "x2"]}
并检查条件并创建numpy数组(因此之前关于效率的问题)
outpts = []
for var in vars_outputs:
if var in missing_labels.keys():
outpts.append(my_df[missing_labels[var][0]][-1]/my_df[missing_labels[var][1]][-1])
else:
outpts.append(my_df[var][-1])
outpts = np.array(outpts)
在我看来这太复杂了,但我想不出更简单的方法(特别是因为我需要在我的numpy输出数组中有这个特定的顺序)
我的另一个想法是在数据框中添加我想要的操作的列,但因为有大约8000个标签我不知道它是否是最好的,因为我必须要看在此预处理步骤之后进入所有这些标签
非常感谢
答案 0 :(得分:1)
这是最终的代码,np.fromiter()完成了这个技巧并允许通过使用列表理解来减少行数
df = pd.read_excel(path)
print(df.columns)
输出[' x1',' x2']
vars_outputs = ["x1", "x2", "ratio_x1_x2"]
missing_labels = {"ratio_x1_x2" : ["x1", "x2"]}
it = [df[missing_labels[var][0]].iloc[-1]/df[missing_labels[var][1]].iloc[-1] if var in missing_labels
else df[var].iloc[-1] for var in vars_outputs]
t = np.fromiter(it, dtype = float)
答案 1 :(得分:0)
谢谢@hpaulj,这对我将来可能非常有用。我不知道使用fromiter()
import timeit
setup = '''
import numpy as np
H, W = 400, 400
it = [(1 + 1 / (i + 0.5)) ** 2 for i in range(W) for j in range(H)]'''
fns = ['''
x = np.array([[(1 + 1 / (i + 0.5)) ** 2 for i in range(W)] for j in range(H)])
''', '''
x = np.fromiter(it, np.float)
x.reshape(H, W)
''']
for f in fns:
print(timeit.timeit(f,setup=setup, number=100))
# gives me
# 6.905218548999983
# 0.5763416080008028
编辑PS你的for循环可能是某种迭代器,如
it = [my_df[missing_labels[var][0]][-1]
/ my_df[missing_labels[var][1]][-1] if var in missing_labels
else my_df[var][-1] for var in var_outputs]