我正在使用400.000行数据框(实际上是更大的数据框,但出于测试目的,我使用此维度)。
我需要根据两个条件将多个文件导出到txt / csv:#RIC和日期。
围绕这些条件变得非常缓慢,因此,我正在寻找更快的方法来实现这一目标。
这是我的初衷:
def SaveTxt(df, output_folder=None):
# Start time
start_time = time.time()
# Data Frame with date
df['Date'] = pd.to_datetime(df['Date-Time']).dt.date
dates = df['Date'].unique()
ticks = df['#RIC'].unique()
for tick in ticks:
for date in dates:
# print(date, tick)
# Filtering by instrument and date
temp_df = df[(df['#RIC'] == tick) & (df['Date'] == date)]
if temp_df.empty:
pass
else:
# Saving files
if output_folder in [None, ""]:
temp_df.to_csv("%s_%s.txt" % (date, tick))
else:
temp_df.to_csv("%s\\%s_%s.txt" % (output_folder, date, tick))
# Elapsed time
elapsed_time = time.time() - start_time
elapsed_time = time.strftime("%H:%M:%S", time.gmtime(elapsed_time))
# Priting elapsed time
print('Elapsed time: %s' % elapsed_time)
对于400.000行(相当于5天的数据),运行此脚本需要3分钟。一年下来,花了6个小时,而我没有尝试10年,但是我认为这不是一个好主意。
解决方案
我试图从 df 中删除每个循环中使用的数据,但是这种情况不起作用(也许这将删除数据帧的大小并加快代码的速度):
df = df[(df['#RIC'] != tick) & (df['Date'] != date)]
我认为这应该删除数据框中的每个滴答和日期,但它是单独应用此条件的。
如果您能解决此问题,我将不胜感激。
谢谢
修改
不知道这是否是共享数据样本的最佳方法(我无法通过代理上传)
#RIC Date Price Volume DIJF21 16/10/2019 4.64 15 DIJF21 16/10/2019 4.64 40 DIJF21 16/10/2019 4.64 100 DIJF21 16/10/2019 4.64 5 DIJF21 16/10/2019 4.64 1765 DIJF21 16/10/2019 4.64 10 DIJF21 16/10/2019 4.64 100 DIJF21 16/10/2019 4.64 1000 DIJF21 16/10/2019 4.64 5 DIJF21 16/10/2019 4.64 20 DIJF21 16/10/2019 4.64 80 DIJF21 16/10/2019 4.64 25 DIJF21 16/10/2019 4.64 25 DIJF21 16/10/2019 4.64 150 DIJF20 15/10/2019 4.905 2000 DIJF20 15/10/2019 4.905 2000 DIJF20 15/10/2019 4.903 10
答案 0 :(得分:4)
我建议您考虑使用协程 https://docs.python.org/3/library/asyncio-task.html
类似的东西:
import asyncio
df['Date'] = pd.to_datetime(df['Date-Time']).dt.date
dates = df['Date'].unique()
ticks = df['#RIC'].unique()
async def tick_func(tick):
for date in dates:
temp_df = df[(df['#RIC'] == tick) & (df['Date'] == date)]
if temp_df.empty:
pass
else:
if output_folder in [None, ""]:
temp_df.to_csv("%s_%s.txt" % (date, tick))
else:
temp_df.to_csv("%s\\%s_%s.txt" % (output_folder, date, tick))
asyncio.new_event_loop()
asyncio.set_event_loop(asyncio.new_event_loop())
loop = asyncio.get_event_loop()
tasks = [tick_func(tick) for tick in ticks]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
答案 1 :(得分:1)
我快速地回答了这个问题,似乎瓶颈是用于将数据按for
和tick
分组的双重嵌套date
循环。
也许您可以考虑使用groupby
function在单个函数调用中执行groupby
操作。代码看起来像这样:
grouped_df = df.groupby(['#RIC', 'Date'])
打印grouped_df
以确保它看起来像您期望的样子。然后,您可以遍历此分组的数据帧一次,然后将不同的组保存到文件系统中(根据需要)。
请告诉我这是否可行,或者您是否遇到任何其他问题。
编辑:要跟踪@Thales注释,有一些online resources讨论了如何将大型数据帧保存到csv文件中。从这些资源中,我喜欢使用numpy的建议。
以下是一个示例(摘自上面共享的链接之一):
aa.to_csv('pandas_to_csv', index=False)
# 6.47 s
df2csv(aa,'code_from_question', myformats=['%d','%.1f','%.1f','%.1f'])
# 4.59 s
from numpy import savetxt
savetxt(
'numpy_savetxt', aa.values, fmt='%d,%.1f,%.1f,%.1f',
header=','.join(aa.columns), comments=''
)
# 3.5 s
答案 2 :(得分:1)
事先提供数据样本以测试答案将很有帮助。像这样,我只是希望它能正常工作;)
您应该能够将groupby与自定义函数一起使用,该自定义函数将应用于每个组,如下所示:
def custom_to_csv(temp_df, output_folder):
date, tick = temp_df.name
# Saving files
if output_folder in [None, ""]:
temp_df.to_csv("%s_%s.txt" % (date, tick))
else:
temp_df.to_csv("%s\\%s_%s.txt" % (output_folder, date, tick))
df.groupby(['Date', '#RIC']).apply(custom_to_csv, (output_folder))
编辑:已更改
df
至temp_df
和(output_folder,)
至(output_folder)