【发布时间】:2021-05-02 11:54:35
【问题描述】:
我有一个交易数据集(40k 行,45 列,11 MB RAM),其 ID 跟踪整个交易过程(发送、取款、退款),我需要根据“参考号”列中的值重组 Dataframe,以便与此事务相关的所有数据都在一行中。
我做什么: 加载源Dataframe,对其进行排序,逐行迭代以一次过滤一个ID的出现,迭代最终的Dataframe列并将相应的值分配给本地字典。 最后,连接字典并创建一个新的数据框(大约 1/2 * 40k 行,69 列)。
根据我的测试,for 循环创建 Dict 键(对于 dictOfCols.items() 中的 x、y)消耗了 85% 的所需时间 有更好的方法吗? 目前,此脚本在具有 8 GB RAM 的单核 AMD Epyc(服务器)上需要 30 多分钟。
dictOfCols 包含 3 种可能的交易类型(发送、取款、退款)的键(最终 DF 列名称)和值(列表 [源 DF 列名称])对。简化示例:
dictOfCols = {'reference_number': ['Reference Number', 'Reference Number', 'Reference Number'], 'send_Destination_Country': ['Destination Country', None, None], 'send_ToCountry/Countrpart': ['ToCountry/Countrpart', None, None], 'payout_Destination_Country': [None, 'Destination Country', None], 'payout_ToCountry/Countrpart': [None, 'ToCountry/Countrpart', None], 'bestpay': [None, None, None], 'send': ['Operation', None, None], 'send_DocumentId': ['DocumentId', None, None], 'send_Related_Document_Id': ['Related Document Id', None, None], 'send_Date': ['Date', None, None], 'payout': [None, 'Operation', None], 'payout_documentId': [None, 'DocumentId', None], 'payout_Related_Document_Id': [None, 'Related Document Id', None], 'time_payout': [None, 'Related Document Date', None], 'refund': [None, None, 'Operation'], 'cancelled_time': [None, None, 'Date'], 'send_Point': ['Point', None, None], ....}
DF 看起来像这样: https://docs.google.com/spreadsheets/d/1OhWu_GrqwZBasuPdGFGynBuDXO7fuBjbFOCjrcIPFis/edit#gid=0
我的代码:
data = []
df_master = df_master.sort_values(by='Reference Number', axis='index')
df_master = df_master.set_index('Reference Number', drop=False)
df_master = df_master.sort_index()
ref_cols = df_master['Reference Number'].unique().tolist()
for i in ref_cols:
local = df_master.loc[df_master['Reference Number'] == i]
if local.empty:
continue
# creates slices of local dataframe based on Operation type
send = local.loc[local['Operation'] == 'SEND']
payout = local.loc[local['Operation'] == 'PAYOUT']
refund = local.loc[local['Operation'] == 'REFUND']
# if len of any DF is more than 1, raise error
lenCheck([send, payout, refund])
dict = {}
# create Dict of one Refenrece number, assign values based on column names from dictOfCols
for x, y in dictOfCols.items():
if (y[0] is not None and send.empty == False):
dict[x] = send.iloc[0][y[0]]
elif (y[1] is not None and payout.empty == False):
dict[x] = payout.iloc[0][y[1]]
elif (y[2] is not None and refund.empty == False):
dict[x] = refund.iloc[0][y[2]]
else:
dict[x] = False
# raise ValueError
data.append(dict)
df_master.loc[local.index, 'Drop'] = 1
df = pd.DataFrame(data)
我加快进程的唯一想法是创建源 Dataframe 块并使用多处理。
【问题讨论】:
-
您的问题不清楚。请解释你在代码中做了什么。其他几个问题 - 这里的 dictOfCols 是什么? lenCheck 在这里有什么用?它是什么?另外,不要发布输出df的图像。使用 df.to_dict() 并在此处发布字典。
-
@Nk03:您能详细说明一下不清楚的地方吗?我似乎已经在原帖中回答了你所有的问题。问题是缓慢的内部 For 循环。 dictOfCols 基本上是帖子中描述的列名映射。 lenCheck 是评论所说的 - 检查任何操作类型是否包含超过 1 行,因为每个事务只能包含最大值。 1 次发送,最多 1 次付款和最多 1 次退款操作。输出应包含 dictOfCols 对象键中描述的列,当然还有与这些列对应的数据。谢谢。
标签: python pandas dataframe multiprocessing