利用Python快速进行数据探查

孤者浪人 提交于 2020-07-24 05:56:53

工作中你是否遇见这样的问题:

  • 接手新业务时需要了解数十上百张的数据库表结构;
  • 表中的数据量级均是百万级以上;
  • 希望可以批量快速生成如下表格。

file 数据探查结果表

如果你遇到了以上的问题,恭喜你,本文可以帮助你解决!

1、解决思路

但有人会有疑问,Python进行数据探查不是非常简单的事吗,一个函数分分钟搞定,还有必要专门介绍吗。如果你这样想就too yong too simple了。

你可以回想下,当我们采用descirbe()函数时,默认的前提是已经将数据读入了Python之中。但你可曾想过,实际工作中数据读入也会成为一种问题。对的,当数据量级一旦达到百万以上甚至更多时,Python读取数据的效率就很低了。读取一张表可能就要半小时以上,几十张表的话差不多就得一天了。这样低效的方法,肯定是不可取的。

本文就是来源于工作中的实际需求,在上述的方式行不通时,我转变思路寻找了另一种方式。具体的逻辑思路如下:

file

也就是说,为了快速进行探查,我们可以不用进行全表读入,只需对每个表每个字段进行分组查询就可以了。但如何将SQL查询语句进行循环呢?采用字符串的格式化输出!

2、代码实现

首先我们导入相关包

import pymysql 
import pandas as pd
import datetime as dt
start=dt.datetime.now()  #为了计算程序执行时间

将数据库的连接和查询抽象成一个函数,在此我设置的是返回数据框格式数据

#定义数据查询函数
def sql_inquiry(sql):
  conn= pymysql.connect(host="localhost",port=****,user='****',
                            passwd='****',db="test_titanic",charset="utf8")
  cur=conn.cursor()
  cur.execute(sql)
  result=cur.fetchall()
  cols=[a[0] for a in cur.description] #获得字段名称信息
  df=pd.DataFrame(result,columns=cols)
  conn.commit()
  cur.close()
  conn.close()
  return df

准备工作做好后,我们可以输入我们要进行探查的表名称。

table_name=['test','train']

如果我们想获得这些表的字段名称、注释、类型和行数的话,可以通过数据框的信息表获得。这个地方要注意的就是:为了便于循环,根据每个表建立了一条SQL语句,把所有的语句组合成了一个列表。

table_sql=[]
for i in range(len(table_name)):
    table_sql.append('''select t1.table_name as table_name,t1.column_name as column_name,t1.column_type as column_type,
      t1.column_comment as column_comment ,t2.table_rows as table_rows
      from information_schema.columns as t1,information_schema.`tables` as t2
      where t1.table_schema=t2.table_schema and t1.table_name=t2.table_name and t1.table_name='{}' and t1.table_schema='test_titanic'
      '''.format(table_name[i]))

接下来,就是根据这个SQL列表进行查询获得数据,然后继续对字段进行循环查询。

writer=pd.ExcelWriter("table_des.xlsx")#为了导出数据
table_col_name=[]
row=0
for j in range(len(table_sql)):  #对表SQL进行循环
    table_col_name.append(sql_inquiry(table_sql[j])) #将每个表查询得到的数据框组成列表
    table_col_stat=[]
    col_sql=[]
    for s in range(len(table_col_name[j])): #对每个表信息的字段进行循环
        col_sql.append('''select min({1}) as value_min, max({1}) as value_max,sum(case when {1} is not null then 1 end ) as num_classification,
          sum(case when {1} is null then num else 0 end) as null_num,sum(num) as rows_num
          from
            (select {1} ,count(1) as num
            from  
            {0} group by {1})t1'''.format(table_name[j],table_col_name[j].iloc[s,1]))
# 根据字段的SQL语句进行查询并转换成列表       
        col=sql_inquiry(col_sql[s]).iloc[0,:].tolist()
#将字段名称拼接进列表中
        table_col_stat.append([table_col_name[j].iloc[s,1]]+col)
#转换为数据框
    table_des=pd.DataFrame(table_col_stat,columns=["name","value_min","value_max","num_classification","null_num","rows_num"])
#计算字段的空值率并以百分比形式显示
    table_des["null_rate"]=table_des["null_num"]/table_des["rows_num"]
    table_des["null_rate"]=table_des["null_rate"].apply(lambda x :format(x,".2%"))
#合并数据框
    table_des=pd.merge(table_col_name[j],table_des,how="inner",left_on="column_name",right_on="name")
    table_des.drop(["table_rows","name"],axis=1,inplace=True)
#写入Excel文档
    table_des.to_excel(writer,startcol=1,startrow=row,index=False)
    row+=table_des.shape[0]+4
#保存文档并计算程序用时
writer.save()
elapsed = (dt.datetime.now()- start)
print("Time used:",elapsed)
print ("\a")

完整执行完程序,最后你就能快速生成前文中的数据探查表了,即使表的量级很大。根据这些表,你可以快速地了解表结构。其实代码并不复杂,难的是我们需要找到解决问题的有效思路。

本文仅供学习之用,版权归原作者所有,如有侵权请联系删除。

在学习Python的道路上肯定会遇见困难,别慌,我这里有一套学习资料,包含40+本电子书,800+个教学视频,涉及Python基础、爬虫、框架、数据分析、机器学习等,不怕你学不会! https://shimo.im/docs/JWCghr8prjCVCxxK/ 《Python学习资料》

关注公众号【Python圈子】,优质文章每日送达。

file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!