Python Pandas - Использование to_sql для записи больших кадров данных в кусках

Я использую функцию 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)

Ответы

Ответ 1

Обновление: эта функциональность была объединена в pandas master и будет выпущена в 0.15 (возможно, в конце сентября), благодаря @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.