熊猫to_sql-追加DataFrame

时间:2019-02-21 14:01:24

标签: python mysql pandas dataframe sqlalchemy

我一直在努力开发一种产品,该产品的核心是日常执行数据分析Python 3.7.0脚本。每天午夜,它将处理大量数据,然后将结果导出到两个MySQL表中。第一个只包含与当天有关的数据,而另一个表将包含所有执行的并置数据。

要举例说明我当前拥有的内容,请参见下面的代码,假设df是通过数据分析生成的最终DataFrame:

import pandas as pd
import sqlalchemy

engine = sqlalchemy.create_engine(r"mysql+pymysql://user:psswd@localhost/pathToMyDB")

df = pd.DataFrame({'Something':['a','b','c']})

df.to_sql('DReg', engine, index = True, if_exists='replace') #daily database
df.to_sql('AReg', engine, index = False, if_exists='append') #anual database

正如您在第二个to_sql函数的参数中看到的那样,我没有为anual数据库设置索引。但是,经理要求我这样做,创建一个围绕一个简单规则的索引:这将是一个自动递增的数字索引,该索引将自动为存储在数据库中与其位置相对应的每一行分配一个数字。

因此,基本上,我第一次保存df时,数据库应如下所示:

index   Something
0       a
1       b
2       c

第二次执行:

index   Something
0       a
1       b
2       c
3       a
4       b
5       c

但是,当我在第二个True命令中将索引设置为df.to_sql时(将其转换为df.to_sql('AReg', engine, index = True, if_exists='append')),在两次执行后,数据库最终看起来像这样:

index   Something
0       a
1       b
2       c
0       a
1       b
2       c

我做了一些研究,但是找不到允许这种自动增加索引的方法。我考虑过在每次执行时都读取anual数据库,然后使数据框的索引适应该数据库,但是我的数据库很容易变得非常庞大,这将使其执行速度异常缓慢(并且还禁止我同时在两台计算机上执行同一数据分析,而无需损害我的索引)。

那么,使该索引起作用的最佳解决方案是什么?我在这里想念什么?

2 个答案:

答案 0 :(得分:3)

尽管Pandas有很多导出选项,但其主要目的并不是要用作数据库管理api。数据库通常需要管理索引。

我建议设置index=False, if_exists='append'并使用自动递增索引创建表:

CREATE TABLE AReg (
     id INT NOT NULL AUTO_INCREMENT,
     # your fields here
     PRIMARY KEY (id)
);

答案 1 :(得分:0)

这是我的解决方案。 SQL + Python。 使用SQL获取最大索引ID,而不是读取整个表。它在DB和python上快速且轻负载。 在mysql中,我们手动获取最大ID。在Oracle中,我们可以通过高级sql命令获取最大序列ID。

import pandas as pd
from pprint import pprint
from sqlalchemy import create_engine


db_name = 'temp'
table_name = 'tmp_table'
index_name = 'id'
mysql_url = f'mysql+mysqlconnector://root:Root123@192.168.100.200:13306/{db_name}'
engine=create_engine(mysql_url)

def to_sql_seq(df,table_name=table_name, engine=engine):

    sql_get_max_id = f'select max({index_name}) as id from {table_name}'

    max_id = pd.read_sql(sql_get_max_id, engine)[index_name][0]
    new_id_base = max_id+1
    df.index +=new_id_base
    df.index.name=index_name
    df.to_sql(table_name,engine,if_exists='append')
    return
#Check the current database record
current_table = pd.read_sql(f"select * from {table_name}",engine)
pprint(current_table)

#Simu the new data
new_data = [1,2,3,4]
new_table = pd.DataFrame(new_data,columns=['value'])
to_sql_seq(new_table)

#show the index auto_increment result
inserted_table = pd.read_sql(f'select * from {table_name}',engine)
pprint(inserted_table)

并输出

   id  value
0   1    123
1   2    234
2   3      1
3   4      2
4   5      3
5   6      4
   id  value
0   1    123
1   2    234
2   3      1
3   4      2
4   5      3
5   6      4
6   7      1
7   8      2
8   9      3
9  10      4