【问题标题】:Python Pandas - Using to_sql to write large data frames in chunksPython Pandas - 使用 to_sql 以块的形式写入大数据帧
【发布时间】:2014-07-23 08:26:34
【问题描述】:

我正在使用 Pandas 的 to_sql 函数写入 MySQL,由于帧大小过大(1M 行,20 列)而超时。

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_sql.html

有没有更正式的方法来分块数据并以块的形式写入行?我已经编写了自己的代码,这似乎有效。不过,我更喜欢官方解决方案。谢谢!

def write_to_db(engine, frame, table_name, chunk_size):

    start_index = 0
    end_index = chunk_size if chunk_size < len(frame) else len(frame)

    frame = frame.where(pd.notnull(frame), None)
    if_exists_param = 'replace'

    while start_index != end_index:
        print "Writing rows %s through %s" % (start_index, end_index)
        frame.iloc[start_index:end_index, :].to_sql(con=engine, name=table_name, if_exists=if_exists_param)
        if_exists_param = 'append'

        start_index = min(start_index + chunk_size, len(frame))
        end_index = min(end_index + chunk_size, len(frame))

engine = sqlalchemy.create_engine('mysql://...') #database details omited
write_to_db(engine, frame, 'retail_pendingcustomers', 20000)

【问题讨论】:

  • fwiw,我不得不做这件事。
  • 目前没有官方解决方案,但我们肯定会接受补丁来实现这一点(read_sql (github.com/pydata/pandas/issues/2908) 的块大小存在问题,您可以随时打开一个这个)。
  • 我创建了一个问题。 @joris-如果您不介意,请在此处添加评论并支持我:)。 github.com/pydata/pandas/issues/7347
  • 为什么不直接将数据导出为csv文件(必须是表格格式),然后使用load data infile命令?

标签: python mysql sql pandas sqlalchemy


【解决方案1】:

更新:此功能已合并到 pandas master 中,并将在 0.15(可能是 9 月底)发布,感谢@artemyk!见https://github.com/pydata/pandas/pull/8062

所以从 0.15 开始,您可以指定 chunksize 参数,例如只需这样做:

df.to_sql('table', engine, chunksize=20000)

【讨论】:

  • 完美,它拯救了我的一天!
【解决方案2】:

在回答 question 时提供了漂亮的惯用函数块

在您的情况下,您可以像这样使用此功能:

def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
    for i in xrange(0, len(l), n):
         yield l.iloc[i:i+n]

def write_to_db(engine, frame, table_name, chunk_size):
    for idx, chunk in enumerate(chunks(frame, chunk_size)):
        if idx == 0:
            if_exists_param = 'replace':
        else:
            if_exists_param = 'append'
        chunk.to_sql(con=engine, name=table_name, if_exists=if_exists_param)

唯一的缺点是它不支持在 iloc 函数中对第二个索引进行切片。

【讨论】:

    【解决方案3】:

    从一个表读取并以块的形式写入另一个表......

    [myconn1 ---> 源表],[myconn2----> 目标表],[ch= 10000]

    for chunk in pd.read_sql_table(table_name=source, con=myconn1, chunksize=ch):
        chunk.to_sql(name=target, con=myconn2, if_exists="replace", index=False,
                     chunksize=ch)
        LOGGER.info(f"Done 1 chunk")
    

    【讨论】:

      猜你喜欢
      • 2018-05-04
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 2018-05-12
      • 2020-01-24
      • 2017-05-19
      相关资源
      最近更新 更多