【发布时间】:2016-01-07 15:44:30
【问题描述】:
我将 pandas 用于 ETL 过程。我查询数据库,将结果放入数据框中;数据框非常大(1M 行 * 50 列)。数据框主要由字符串和日期组成。
我使用 pandas 的apply() 函数来进行所有的转换。问题是我的转换在字符串上包含多个分支。
df['merged_contract_status'] = df.apply(lib.merged_contract_status, axis=1)
df['renewed'] = df.apply(lib.contract_renewed, axis=1)
df['renewal_dt'] = df.apply(lib.contract_renewed_date, axis=1)
....
我有一堆这样的转变。 我调用的函数:
def merged_contract_status(row):
if row['tbm_contract_status'] is not np.nan:
mergedContractStatus = row['tbm_contract_status']
else:
mergedContractStatus = row['ccn_status']
return mergedContractStatus
def contract_renewed(row):
ccn_activation_dt = row['ccn_activation_dt']
ccn_status = row['ccn_status']
f_init_val_dt = row['f_init_val_dt']
f_nat_exp_dt = row['f_nat_exp_dt']
spr_spo_code = row['spr_spo_code']
csp_status_sep_1 = row['csp_status_sep_1']
csp_begin_dt_sep_1 = row['csp_begin_dt_sep_1']
ctt_type_1 = row['ctt_type_1']
csp_status_sep_2 = row['csp_status_sep_2']
csp_begin_dt_sep_2 = row['csp_begin_dt_sep_2']
ctt_type_2 = row['ctt_type_2']
csp_status_sep_3 = row['csp_status_sep_3']
csp_begin_dt_sep_3 = row['csp_begin_dt_sep_3']
ctt_type_3 = row['ctt_type_3']
csp_begin_dt_sep_father = row['csp_begin_dt_sep_father']
csp_end_dt_sep_father = row['csp_end_dt_sep_father']
todayDate = datetime.datetime.today()
if spr_spo_code == 'PCC':
if ctt_type_1 == 'NORMAL' and ccn_activation_dt is not None and csp_begin_dt_sep_1 is not None and csp_begin_dt_sep_1>(ccn_activation_dt+timedelta(365)):
return 'Y'
elif ctt_type_2 == 'NORMAL' and ccn_activation_dt is not None and csp_begin_dt_sep_2 is not None and csp_begin_dt_sep_2>(ccn_activation_dt+timedelta(365)):
return 'Y'
elif ctt_type_3== 'NORMAL' and ccn_activation_dt is not None and csp_begin_dt_sep_3 is not None and csp_begin_dt_sep_3>(ccn_activation_dt+timedelta(365)):
return 'Y'
else:
return 'N'
else:
if (f_init_val_dt is None and f_nat_exp_dt is None and
ccn_activation_dt is not None and
ccn_activation_dt < (todayDate- timedelta(365)) and
(csp_begin_dt_sep_father <= todayDate and csp_begin_dt_sep_father >= todayDate and ccn_status=='ACTIVATED')):
return 'Y'
elif f_init_val_dt is not None and f_nat_exp_dt is not None and f_init_val_dt <= todayDate and f_nat_exp_dt >= todayDate and ccn_status=='ACTIVATED' and ccn_activation_dt is not None and ccn_activation_dt < (todayDate- timedelta(365)):
return 'Y'
else:
return 'N'
每次我在我的 df 上调用 apply 时,pandas 都会遍历整个 df,大约需要 10 分钟。我觉得那 10 分钟没问题;我知道我无法提高性能。 但是有没有办法避免多重循环?熊猫可以只循环一次并完成我想要的所有转换吗?
编辑:很难给你数据,因为数据框很大,而且它是用 sql 查询构建的。 我想要的帮助是一种只在数据帧中循环一次的方法,我不想改进每个函数(对于那些在字符串上分支是不可能的)
谢谢
【问题讨论】:
-
如果你展示你的函数在做什么、一些示例数据、重现你的df和所需的df的代码会有所帮助
-
也许 .groupby().agg() 方法会有所帮助?例如:stackoverflow.com/questions/22128218/…
标签: python performance pandas apply