pandas的DataFrame是常用的数据分析数据格式,Oracle数据库是常用的结构化数据存储方式,通常做数据分析牵涉到大量的数据时,我们必须通过借助一定的工具进行,而不能单单依靠excel,因此通过pandas进行数据分析,以Oracle作为存储数据的媒介便成为了我们最方便或者灵活的选择,同时DataFrame的数据格式样式和oracle的结构化表非常的相似,将DataFrame格式的数据直接写入oracle以及将oracle的数据表直接读取为DataFrame便极大的简化了数据格式转换的工作,非常的方便。
本次我们通过sqlalchemy库登录oracle,通过pandas的相关函数和方式实现数据的增删改查。
首先先导入sqlalchemy库的create_engine,
通过 engine = create_engine("dialect+driver://username:password@host:port/database")初始化连接
参数说明:
dialect,是数据库类型包括:sqlite, mysql, postgresql, oracle, mssql等
driver,指定连接数据库的API,如:`psycopg2``, ``pyodbc``, ``cx_oracle``等,为可选关键字。
username,用户名
password,密码
host,网络地址,可以用ip,域名,计算机名,当然是你能访问到的。
port,数据库端口。
database,数据库名称。
例如建立mysql的连接方式为:(echo=True,会显示在加载数据库所执行的SQL语句,可不选此参数,默认为False)
engine = create_engine("mysql://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)
建立oracle的连接方式为:
engine = create_engine("oracle://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)
from sqlalchemy import create_engine
engine = create_engine("oracle://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)
由此,我们便初始化了数据库的连接,也就是说已经登录了数据库
我们用pandas的read_sql方法实现数据库的查询、删除、更新操作,用to_sql方法实现数据的写入。
read_sql
首先看read_sql官方介绍:pd.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)
参数说明:
sql,执行的sql,可为查询、删除、创建、更新等等的sql,在此可直接指定表名称,默认就是select * from tablename
con,指定的数据库连接,即con=engine,也就是我们刚才初始化的数据库连接engine
index_col,查询时,指定那一列为DataFrame的index,也可以是多列['a','b'],此时就生成了Multindex
coerce_float,boolean,默认为True,尝试转换float的值,用于设置sql查询的结果
params,list, tuple or dict, 可选关键字, 默认为:None,要传递给执行方法的参数列表。不太懂这个关键字,一般情况用不到
parse_dates, list or dict, 默认为 None,要解析为日期时间的字段
columns,查询时指定选择那些列,即select * from 中的*,默认全部列
chunksize,int,默认为None,如果指定数值,则返回一个迭代器,指定的数值为迭代器内数据的行数
data=pd.read_sql('stock_basic',engine)
data.head()
Out[41]:
ts_code symbol name area industry market list_date
0 000702.SZ 000702 正虹科技 湖南 饲料 主板 19970318
1 000703.SZ 000703 恒逸石化 广西 化纤 主板 19970328
2 000705.SZ 000705 浙江震元 浙江 医药商业 主板 19970410
3 000707.SZ 000707 *ST双环 湖北 化工原料 主板 19970415
4 000708.SZ 000708 大冶特钢 湖北 特种钢 主板 19970326
data=pd.read_sql('stock_basic',engine,index_col='ts_code',columns=['symbol','industry'])
data.head()
Out[43]:
symbol industry
ts_code
000702.SZ 000702 饲料
000703.SZ 000703 化纤
000705.SZ 000705 医药商业
000707.SZ 000707 化工原料
000708.SZ 000708 特种钢
需注意:使用read_sql方式执行诸如drop /create/truncate等操作时,因没有返回结果数据会报错(但已执行成功),针对如此情况,若需要程序继续运行,可尝试加入try捕捉错误,继续运行程序。
to_sql
to_sql为DataFrame的方法,用于写入数据库数据,可等同于create/insert
官方介绍:DataFrame.to_sql(self, name, con, schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None)
关键参数说明:
name,数据库表名
con,指定的数据库连接,即con=engine,也就是我们刚才初始化的数据库连接engine
schema,指定样式,不明白有什么用处
if_exists,{'fail', 'replace', 'append'}, 默认为'fail',即指定当数据库表存在时的处理方式,默认为fail,挂起一个错误
* fail: 挂起一个错误
* replace: drop掉原来的表,重新创建
* append: 在原来表基础上插入数据
index,boolean,默认为True,指定DataFrame的index是否一同写入数据库
index_label,在index关键字为True时,指定写入的index的字段名称,默认为None时,字段名称为index
chunksize,int,默认为None,如果指定数值,则返回一个迭代器,指定的数值为迭代器内数据的行数。当写入的数据量较大时,最好指定此关键字的数值
dtype,dict, 可选关键字,默认为None,即指定写入的字段字符类型,注意做好指定字符类型,因默认写入的数据类型数是colb,若没有指定数据类型,估计会报错。
to_sql用法实战
DataFrame.to_sql方法可直接将DataFrame数据写入的数据库中的表,表在数据库中可存在,可不存在,因不同类型的数据库其字符类型不相同,若不指定写入数据的字符类型,往往会出现我们意想不到的错误,故为避免错误,指定写入的数据类型是非常有必要的,特别是表不存在时,我们直接用to_sql方法,相当于创建了一个表。
写入数据的字符类型可通过dtype关键字来指定,为方便起见我们定义了一个函数,自动获取DataFrme各列的数据类型,生成字典。
#导入支持oracle的数据类型
from sqlalchemy.dialects.oracle import \
BFILE, BLOB, CHAR, CLOB, DATE, \
DOUBLE_PRECISION, FLOAT, INTERVAL, LONG, NCLOB, \
NUMBER, NVARCHAR, NVARCHAR2, RAW, TIMESTAMP, VARCHAR, \
VARCHAR2
#定义函数,自动输出DataFrme数据写入oracle的数类型字典表,配合to_sql方法使用(注意,其类型只能是SQLAlchemy type )
def mapping_df_types(df):
dtypedict = {}
for i, j in zip(df.columns, df.dtypes):
if "object" in str(j):
dtypedict.update({i: VARCHAR(256)})
if "float" in str(j):
dtypedict.update({i: NUMBER(19,8)})
if "int" in str(j):
dtypedict.update({i: VARCHAR(19)})
return dtypedict
由此便创建了函数mapping_df_types,自动获取DataFrame各列的字符类型,用于dtype关键字
data_base.to_sql('stock_class',engine,index=False,if_exists='append',dtype=dtypedict,chunksize=100)
OK,到此我们便完成了数据的写入,同时也指定的了写入的数据类型,当‘stock_class’表存在时,在原来数据基础上插入数据,若不存在,则自动生成‘stock_class’表,表内每个字段的字符类型也同时指定了。