遇到个代码优化的问题。。想请教下。。这段代码,结构或是哪里该如何优化下,以提高运行速度。。
大致情况先介绍下:
1. 代码需要考虑指定文件的输出---也就是相应数据是否需要计算;代码中的if output1 / output2 in condition,即是用来判断是否需要进行计算;
2. 计算需要分步骤进行。大致是先根据原始数据,计算原始数据的x1值(该步骤已经执行)。再根据x1值,计算相应的x1x2值,和x3值。然后将x1x2和x3拼接起来。
3. 数据量是10W行,为时间数据。。分两种情况进行计算(也就是两种情况的结果输出)。一种是每行时间数据,均要输出一个结果。另一种是对某个字段进行分组,然后根据分组来输出计算结果(比如企业)。
具体代码如下:
t05 = time.time()
#计算x1x2和x3的值(x1值已计算出来)
for i in std_level:
max_std,min_std,l_1,l_2,l_3,l_4,l_5 = std_level[i][0] #生成标准的数据表,用于对照取值
#对原x1的字段的空值填充为0,方便跳过数值0进行数据处理。同时便于后期与目标值比较。
if output1 in condition: #这个情况,是根据用户需求,进行相应的输出。如用户有需求,则执行下面的代码
data['%s_x1'%i].fillna(0,inplace =True)
if output2 in condition:
f_data['%s_x1'%i].fillna(0,inplace =True)
#定义x1x2的函数
#x1为原始数据对应的等级,值为1--6(如原数据缺失,则为空值。为便于判断,需将x1的缺失值填充为0)
#原则是,如x1(数据等级)为空值,则不进行判定(返回空值)。如等级为1或6,单独计算。如等级介于1和6之间,则统一计算。
def tran_x1x2(x):
dj = x['%s_x1'%i]
jc = x[i]
if dj == 0:
return np.NaN #务必要返回np.NaN,否则返回空字符串None,影响后面x2的计算。
else:
if dj not in [1,6]: #根据介于等级1和6之间时的x1x2的计算公式
up = std_level[i][0][int(dj)]
dn = std_level[i][0][int(dj)+1]
return round(dj + (up - jc) / (up -dn),1)
else:
if dj == 1:
return 1.0
else:
return round(dj + (l_5 - jc) / l_5 * 4,1)
#需事先定义好x1x2的函数,方能进行apply。而x1x2的函数定义,又需要事先对x1填充。。所以需要将条件判断,分开两次重复进行
#本来考虑可以将条件判断合并到一起。。但是这样会增加重复的代码量,而且不能保证提高速度。
#我也想用函数的方式来处理,但是不知道如何实现。。具体结构该怎么弄。。。
if output1 in condition:
data['%s_x1x2'%i] = data.apply(tran_x1x2,axis=1) #生成实时数据的x1x2
if output2 in condition:
f_data['%s_x1x2'%i] = f_data.apply(tran_x1x2,axis=1) #生成综合数据的x1x2
#注意顺序,需先计算x1x2的值,才能计算x3的值
def tran_x3(x):
dj = x['%s_x1'%i]
dj_x1x2 = x['%s_x1x2'%i]
dj_x2 = (dj_x1x2 - dj) *10 #计算x2的值。不建议单独生成x2字段,否则字段过多,影响调试查看。
if dj == 0: #等级数据不可能为0,其值原为空值,只是为了便于比较,将空值填充为0处理(第7/9行代码中实现)。
return np.NaN
else:
if dj <= x['TARGET']: #[‘TARGET’]为目标字段,用于比较
return 0
else:
if dj_x2 == 0:
return dj - x['TARGET'] -1
else:
return dj - x['TARGET']
#新的x3存在空值的情况,需要事先填充
if output1 in condition: #这个情况,是根据用户需求,进行相应的输出。如用户有需求,则执行下面的代码
data['%s_x3'%i] = data.apply(tran_x3,axis=1) #生成实时数据的x3
data['%s_x3'%i].fillna(-1,inplace =True) #因x3可能为0,空值需填充为-1,以便区分和格式转换
data['%s_x1x2'%i] = data['%s_x1x2'%i].astype(str) #转字符格式,方便拼接
data['%s_x3'%i] = data['%s_x3'%i].astype(int).astype(str)
data['%s_x1x2x3'%i] = np.where(data['%s_x3'%i]!= '-1',data['%s_x1x2'%i]+data['%s_x3'%i],np.NaN) #生成单因子标识指数
data['%s_x1x2x3'%i] = data['%s_x1x2x3'%i].astype(float) #求X1X2前,需记得将字符串转浮点型格式,否则无法求均值。
if output2 in condition:
f_data['%s_x3'%i] = f_data.apply(tran_x3,axis=1) #生成综合数据的x3
f_data['%s_x3'%i].fillna(-1,inplace=True)
f_data['%s_x1x2'%i] = f_data['%s_x1x2'%i].astype(str) #转字符格式,方便拼接
f_data['%s_x3'%i] = f_data['%s_x3'%i].astype(int).astype(str)
f_data['%s_x1x2x3'%i] = np.where(f_data['%s_x3'%i]!= '-1',f_data['%s_x1x2'%i] + f_data['%s_x3'%i],np.NaN)
f_data['%s_x1x2x3'%i] = f_data['%s_x1x2x3'%i].astype(float)
t06 = time.time()
print(t06-t05)
这段代码,我用10W行的数据来跑,用了24秒左右。。
我发现其中比较耗时的就是要输出output1的计算。。。这个就是计算每行数据的结果,计算量可能较大。
个人觉得代码还有较大的提升空间,只是水平有限,实在不知道如何优化。。
求高手指点