大數據ETL實踐探索(7)---- 使用python 進行oracle 全庫數據描述性及探索性逆向分析


0.簡介

想象以下一個場景,一個合做夥伴想讓你分析一下本身的業務數據,比較慷慨的給出了數據全庫。可是對方的IT 人員沒有精力去協助咱們逐個瞭解數據怎麼辦呢,這時候就須要進行一些針對數據庫的探索性、描述性的數據分析 幫咱們更好的瞭解對方的數據內涵了。html

下面就以Oracle 爲例,使用python 進行全庫數據描述性及探索性逆向分析。python


1. cx_Oracle 簡介與數據類型

說到python 連接Oracle ,就不得不提到cx_Oracle ,cx_Oracle is a module that enables access to Oracle Database and conforms to the Python database API specification.git

cx_Oracle 目前是oracle 官方 出品的python Oracle連接管理包github

cx_Oracle 源代碼:https://github.com/oracle/python-cx_Oracle
文檔:https://cx-oracle.readthedocs.io/en/latest/index.htmlweb

Oracle - cx_Oracle - Python 映射爲:算法

Oracle

cx_Oracle

Python

VARCHAR2
NVARCHAR2
LONG

cx_Oracle.STRINGsql

strshell

CHAR數據庫

cx_Oracle.FIXED_CHARc#

NUMBER

cx_Oracle.NUMBER

int

FLOAT

float

DATE

cx_Oracle.DATETIME

datetime.datetime

TIMESTAMP

cx_Oracle.TIMESTAMP

CLOB

cx_Oracle.CLOB

cx_Oracle.LOB

BLOB

cx_Oracle.BLOB


2.Oracle 12c 新特性容器數據庫

通常來講對於Oracle 高版本的數據庫是向下兼容的,因此咱們目前使用Oracle 12c 進行本次說明。

Oracle 12C引入了CDB與PDB的新特性,在ORACLE 12C數據庫引入的多租用戶環境(Multitenant Environment)中,容許一個數據庫容器(CDB)承載多個可插拔數據庫(PDB)。CDB全稱爲Container Database,中文翻譯爲數據庫容器,PDB全稱爲Pluggable Database,便可插拔數據庫。在ORACLE 12C以前,實例與數據庫是一對一或多對一關係(RAC):即一個實例只能與一個數據庫相關聯,數據庫能夠被多個實例所加載。而實例與數據庫不多是一對多的關係。當進入ORACLE 12C後,實例與數據庫能夠是一對多的關係。下面是官方文檔關於CDB與PDB的關係圖。
在這裏插入圖片描述
簡介詳見:
https://www.cnblogs.com/kerrycode/p/3386917.html

及官方文檔:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/index.html

oracle 執行 SQL :
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/cncpt/sql.html#GUID-DA48618A-A6BB-421A-A10A-02859D8ED9AD


3.Oracle 12c 新建表空間、用戶、表

在windows 下,咱們使用PL/sql 以及sqlplus 進行Oracle 的管理工做,sqlplus 是安裝好Oracle 就自帶了。

3.0 設置oracle sid 數據庫實例名

在cmd 命令行窗口使用sqlplus 以前須要進行數據庫實例名 的指定。

set oracle_sid=orcl

3.1 以管理員帳戶登陸

sqlplus sys/sys as sysdba;

3.2 建立表空間

建立用戶以前須要建立表空間。

# -- 2.1 建立臨時空間
create temporary tablespace test 
tempfile 'E:\table\test.dbf' 
size 5m 
autoextend on 
next 10m  
extent management local;


# -- 2.2 建立數據表空間

create tablespace test_data
logging
datafile 'E:\table\test_data.dbf'
size 10m
autoextend on
next 10m
maxsize unlimited
extent management local;

3.3 建立用戶並指定表空間

有了表空間,咱們能夠在建立用戶的時候給用戶指定表空間。

# -- 3.建立用戶並指定表空間

-- 剛開始用戶名爲 ,提示錯誤ORA-65096:公用用戶名或角色名無效,網上查資料,說是取名前綴必須爲c##,
--因此用戶名也變成了c##test
--首次建立用戶時提示test_data表空間不存,重啓了服務就建立成功
create user c##test identified by test
default tablespace test_data
temporary tablespace test;

3.4 用戶受權

根據須要設置權限

GRANT CREATE ANY VIEW,DROP ANY VIEW,CONNECT,RESOURCE,CREATE SESSION,DBA TO c##test;

3.5 建立樣例表格

爲了咱們後面的分析方便,咱們本身建立兩個樣例表格進行舉例,其實真實的狀況通常是 參照第6小節數據導入導出,進行原始數據的,導入導出。

注意建立表的時候添加了comment ,這樣方便咱們DBA 或者逆向探索時候可以理解表格的含義。通常的真實狀況是,數據庫建表過程當中,良好習慣的DBA 會按照必定的命名規範建表,命名字段及編寫註釋。 這就給咱們逆向理解合做夥伴的業務提供了便利條件。

--創建表 DEPT和刪除表;

DROP TABLE DEPT cascade constraints;
CREATE TABLE DEPT
       (DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
    DNAME VARCHAR2(14) ,
    LOC VARCHAR2(13) ) ;
-- 增長表註釋 
comment on table C##TEST.DEPT
  is '部門表';
comment on column C##TEST.DEPT.deptno
  is '部門編號';
comment on column C##TEST.DEPT.dname
  is '部門名稱';
comment on column C##TEST.DEPT.loc
  is '部門位置';
 
--創建表 EMP和刪除表;
DROP TABLE EMP;
CREATE TABLE EMP
       (EMPNO NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY,
    ENAME VARCHAR2(10),
    JOB VARCHAR2(9),
    MGR NUMBER(4),
    HIREDATE DATE,
    SAL NUMBER(7,2),
    COMM NUMBER(7,2),
    DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES DEPT);
 
---插入dept語句塊;
INSERT INTO DEPT VALUES
    (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES
    (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES
    (40,'OPERATIONS','BOSTON');
 
---插入EMP語句塊;
INSERT INTO EMP VALUES
(7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO EMP VALUES
(7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO EMP VALUES
(7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO EMP VALUES
(7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO EMP VALUES
(7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO EMP VALUES
(7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO EMP VALUES
(7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO EMP VALUES
(7788,'SCOTT','ANALYST',7566,to_date('12-06-1987','dd-mm-yyyy')-85,3000,NULL,20);
INSERT INTO EMP VALUES
(7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO EMP VALUES
(7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO EMP VALUES
(7876,'ADAMS','CLERK',7788,to_date('13-06-1987','dd-mm-yyyy')-51,1100,NULL,20);
INSERT INTO EMP VALUES
(7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO EMP VALUES
(7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO EMP VALUES
(7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
 
 
-- 提交插入
COMMIT;
 
--查詢部分;
select * from emp;
select * from dept;

3.6 數據導入導出

imp/exp ,impdp/expdp須要成對使用

如下分別給出兩個導入樣例

imp c##test/test@orcl file=D:20190506.DMP full=y log=01.log
impdp c##test/test@orcl directory=dir logfile=p_street_area.log job_name=my_job

4.python 環境準備

參考該文章:1.2.4 小節conda基本環境配置
https://blog.csdn.net/wangyaninglm/article/details/89440922

使用以下 requirements.txt 初始化環境

conda create --name DATABASE --file requirements.txt
# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: win-64
backcall=0.1.0=py37_0
blas=1.0=mkl
ca-certificates=2019.1.23=0
certifi=2019.3.9=py37_0
colorama=0.4.1=py37_0
cx_oracle=7.0.0=py37h62dcd97_0
decorator=4.4.0=py37_1
icc_rt=2019.0.0=h0cc432a_1
intel-openmp=2019.3=203
ipykernel=5.1.0=py37h39e3cac_0
ipython=7.5.0=py37h39e3cac_0
ipython_genutils=0.2.0=py37_0
jedi=0.13.3=py37_0
jupyter_client=5.2.4=py37_0
jupyter_core=4.4.0=py37_0
libsodium=1.0.16=h9d3ae62_0
mkl=2019.3=203
mkl_fft=1.0.12=py37h14836fe_0
mkl_random=1.0.2=py37h343c172_0
numpy=1.16.4=py37h19fb1c0_0
numpy-base=1.16.4=py37hc3f5095_0
openssl=1.1.1c=he774522_1
pandas=0.24.2=py37ha925a31_0
parso=0.4.0=py_0
pickleshare=0.7.5=py37_0
pip=19.1.1=py37_0
prompt_toolkit=2.0.9=py37_0
pygments=2.4.0=py_0
python=3.7.3=h8c8aaf0_1
python-dateutil=2.8.0=py37_0
pytz=2019.1=py_0
pyzmq=18.0.0=py37ha925a31_0
setuptools=41.0.1=py37_0
six=1.12.0=py37_0
sqlite=3.28.0=he774522_0
tornado=6.0.2=py37he774522_0
traitlets=4.3.2=py37_0
vc=14.1=h0510ff6_4
vs2015_runtime=14.15.26706=h3a45250_4
wcwidth=0.1.7=py37_0
wheel=0.33.4=py37_0
wincertstore=0.2=py37_0
zeromq=4.3.1=h33f27b4_3
# 爲了能讓jupyter 使用這個 kernel
#直接 切換到 須要顯示 的 隔離環境
conda install ipykernel
#or
conda install -n python_env ipykernel

5.Oracle SQL 全庫全表字段分析

在Oracle 中進行 全庫全表字段分析須要用的一個很是重要的表:USER_TABLES

什麼是USER_TABLES ?

USER_TABLES describes the relational tables owned by the current user. Its columns (except for OWNER) are the same as those in ALL_TABLES.

USER_TABLES 和ALL_TABLES 字段同樣,咱們來看看文檔裏面ALL_TABLES 有哪些有用的字段:

ALL_TABLES

Related Views

  • DBA_TABLES describes all relational tables in the database.

  • USER_TABLES describes the relational tables owned by the current user. This view does not display the OWNER column.

Note:Columns marked with an asterisk (*) are populated only if you collect statistics on the table with the DBMS_STATS package.

對咱們有用的字段拿幾個先看看:

SELECT a.num_rows, a.table_name, b.comments
  FROM user_tables a, user_tab_comments b
 WHERE a.table_name = b.table_name
 ORDER BY num_rows DESC

能夠看到 寫了註釋的表,都展示出來註釋了。
在這裏插入圖片描述
能夠看到剛剛插入完數據,num_rows 沒有更新

隔了一天之後, 數據就有了:
在這裏插入圖片描述
若是想要當即更新USER_TABLES 或者參照下面連接

Oracle manually update statistics on all tables

運行,手動更新:

exec DBMS_STATS.GATHER_DATABASE_STATS;

通常來講,USER_TABLES不會自動更新,oracle 會在閒時或者定時更新這張表。因此入數據之後不必定 多久會看到USER_TABLES 的更新。

SELECT t_column_comments.table_name,
       t_table_comments.comments     表名,
       t_table_comments.num_rows     錶行數,
       t_table_comments.avg_row_len  表平均長度,
       t_column_comments.column_name,
       t_column_comments.comments    字段名
  FROM (SELECT *
          FROM all_col_comments
         WHERE table_name IN (SELECT table_name FROM user_tables)) t_column_comments,
       
       (SELECT a.num_rows, a.table_name, b.comments, a.avg_row_len
          FROM user_tables a, user_tab_comments b
         WHERE a.table_name = b.table_name) t_table_comments

 WHERE t_table_comments.table_name = t_column_comments.table_name
 ORDER BY t_column_comments.table_name

能夠看到以下的導出表基本上符合人的觀察規範,適合進行Oracle 全庫的描述性、探索性數據分析。好比合做夥伴將全庫共享,咱們如何第一時間經過數據瞭解合做夥伴的業務狀況和設計呢。我想能夠經過這樣的手段,首先有一個大體的認識,接下來就是進一步看看樣例數據的樣子了。那麼咱們用這個導出表做爲基礎,寫點python代碼進一步進行數據探索性分析。
在這裏插入圖片描述


6.Oracle python 操做輔助類

經過編寫OracleBaseTool, 這個操做輔助類,主要目的是對於如下一些動做進行封裝:

  • 1.數據庫的連接(初始化)
  • 2.數據庫連接的管理
  • 3.數據庫的查詢管理
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#-------------------------------------------------------------------------------
''' @Author : {SEASON} @License : (C) Copyright 2013-2022, {OLD_IT_WANG} @Contact : {shiter@live.cn} @Software: PyCharm @File : DataBase -- OracleBaseTool @Time : 2019/5/22 17:10 @Desc : '''
#-------------------------------------------------------------------------------

import cx_Oracle

class OracleBaseTool():
    """OracleBaseTool"""

    def __init__(self,user_name,password,ip,service_name):

        self.user_name = user_name
        self.password = password
        self.ip = ip
        self.service_name = service_name
        self.connectObj = ""
        self.connCnt = 0
        self.cursorCnt = 0

    def initOracleConnect(self):
        oracle_tns = cx_Oracle.makedsn(self.ip, 1521, self.service_name)
        if self.connCnt == 0:
            self.connectObj = cx_Oracle.connect(self.user_name, self.password, oracle_tns)
            self.connCnt += 1

    def getConnOracle(self,user_name, password, ip, service_name):
        try:
            self.connectObj = cx_Oracle.connect(user_name + '/' + password + '@' + ip + '/' + service_name)  # 鏈接數據庫
            self.connCnt += 1
        except Exception:
            print(Exception)

    def getOracleConnect(self):
        self.initOracleConnect()
        return self.connectObj

    def closeOracleConnect(self, connectObj):
        connectObj.close()
        self.connCnt -= 1

    def getOracleCursor(self):
        self.initOracleConnect()
        self.cursorCnt += 1
        return self.connectObj.cursor()

    def closeOracleCursor(self, cursorObj):
        cursorObj.close()
        self.cursorCnt -= 1

        if self.cursorCnt == 0:
            print("will close conn")
            self.closeOracleConnect(self.connectObj)

    def selectFromDbTable(self, sql, argsDict=None):
        # 將查詢結果由tuple轉爲list,並返回
        queryAnsList = []
        selectCursor = self.getOracleCursor()
        selectCursor.prepare(sql)
        if argsDict==None:
            queryAns = selectCursor.execute(sql)
        else:
            queryAns = selectCursor.execute(None, argsDict)

        for ansItem in queryAns:
            queryAnsList.append(list(ansItem))

        self.closeOracleCursor(selectCursor)
        return queryAnsList

    def selectFromDbTable_WithTableHead(self, sql, argsDict=None):
        # 將查詢結果由tuple轉爲list,並返回,帶表頭
        queryAnsList = []
        selectCursor = self.getOracleCursor()
        selectCursor.prepare(sql)
        if argsDict==None:
            queryAns = selectCursor.execute(sql)
        else:
            queryAns = selectCursor.execute(None, argsDict)

         # 獲取表的列名
        title = [i[0] for i in selectCursor.description]
        queryAnsList.append(list(title))

        for ansItem in queryAns:
            queryAnsList.append(list(ansItem))


        self.closeOracleCursor(selectCursor)
        return queryAnsList

    def selectFromDbTablefor_SampleData(self, sql, argsDict=None,intSampleNumber = 1):
        '''獲取intSampleNumber 條樣例數據,帶表頭'''
        queryAnsList = []
        selectCursor = self.getOracleCursor()
        selectCursor.prepare(sql)
        if argsDict==None:
            selectCursor.execute(sql)
            queryAns = selectCursor.fetchmany(intSampleNumber)
        else:
            queryAns = selectCursor.execute(None, argsDict)
            queryAns = selectCursor.fetchmany(intSampleNumber)

        # 獲取表的列名
        title = [i[0] for i in selectCursor.description]
        queryAnsList.append(list(title))

        for ansItem in queryAns:
            queryAnsList.append(list(ansItem))

        self.closeOracleCursor(selectCursor)
        return queryAnsList

7.python 連接Oracle 全庫數據採樣

本節主要用到了上面的操做類,使用oracle 的user_tables 獲取數據的全部表名稱,以後按照採樣設置進行連接及採樣,並根據採樣數據計算數據缺失率,以求初步瞭解數據和業務的緊密關聯。最後用pandas 保存爲excel 方便查看。

其中採樣的功能主要用到了Oracle 中的sample 函數,具體你們能夠查看文檔:

Oracle 表採樣

如下腳本主要有兩大功能:

  1. 各個表中數據列缺失值統計(採樣缺失值,如採樣10000條)
  2. 從各個表中獲取數據樣例
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#-------------------------------------------------------------------------------
''' @Author : {SEASON} @License : (C) Copyright 2013-2022, {OLD_IT_WANG} @Contact : {shiter@live.cn} @Software: PyCharm @File : DataBase -- GetSampleData @Time : 2019/5/22 15:41 @Desc : '''
#-------------------------------------------------------------------------------

import pandas as pd
# from __future__ import print_function

import cx_Oracle
import OracleBaseTool
import os
#應對出現 illegal multibyte sequence 問題
os.environ['nls_lang'] = 'AMERICAN_AMERICA.AL32UTF8'


#生成數據庫全部表名、表名註釋及行數
sql_string_all_tables = ''' SELECT a.num_rows, a.table_name, b.comments FROM user_tables a, user_tab_comments b WHERE a.table_name = b.table_name ORDER BY num_rows DESC '''

# sql_string2= '''select a.num_rows, a.TABLE_NAME, b.COMMENTS from user_tables a, user_tab_comments b
# WHERE a.TABLE_NAME = b.TABLE_NAME and a.TABLE_NAME = :content
# order by num_rows desc'''

    #named_params = {'content': 'MZ_FYMXB'}
    # 傳參的sql語句寫法
    # result_list= HIS_oracle_object.selectFromDbTable(sql_string2,named_params)

#生成數據庫全部表名、表名註釋及行數,字段名,字段註釋
sql_string_all_columns = ''' SELECT t_column_comments.table_name, t_table_comments.comments 表名, t_table_comments.num_rows 錶行數, t_table_comments.avg_row_len 表平均長度, t_column_comments.column_name, t_column_comments.comments 字段名 FROM (SELECT * FROM all_col_comments WHERE table_name IN (SELECT table_name FROM user_tables)) t_column_comments, (SELECT a.num_rows, a.table_name, b.comments, a.avg_row_len FROM user_tables a, user_tab_comments b WHERE a.table_name = b.table_name) t_table_comments WHERE t_table_comments.table_name = t_column_comments.table_name ORDER BY t_column_comments.table_name '''

# 連接oracle
test_oracle_obj = OracleBaseTool.OracleBaseTool(
    'c##test', 'test', '127.0.0.1', 'orcl')

result_list = test_oracle_obj.selectFromDbTable(sql_string_all_tables)
result_list_schemaDetail = test_oracle_obj.selectFromDbTable_WithTableHead(
    sql_string_all_columns)


result_list_schemaDetail_pdf = pd.DataFrame(
    result_list_schemaDetail[1:], columns=result_list_schemaDetail[0])

# 設置採樣數據組數,即爲 從表中讀取幾條樣例數據
sample_number = 10000

result_list_schemaDetail_pdf['缺失值比例'] = None
# 採樣5個sample data 做爲column name
for i in range(1, 5+1):
    result_list_schemaDetail_pdf['sample_data'+str(i)] = None


# 獲取5條樣例數據,遍歷每一張表
for x in result_list:
    table_row_number = x[0]
    table_name = x[1]
    table_comments = x[2]
    
    if table_row_number > sample_number*10:
        #大於10000行的表進行採樣
        #select * from table_name sample(10) where rownum<=5
        sql_string_forsampledata = '''select * from ''' + table_name + ''' sample(10) where rownum<=1000'''
    else:
        #小於10000行的表 隨便選
        sql_string_forsampledata = '''select * from ''' + table_name
        
    result_list_sampleData = test_oracle_obj.selectFromDbTablefor_SampleData(
        sql_string_forsampledata, None, sample_number)

    result_list_sampleData_pdf = pd.DataFrame(
        result_list_sampleData[1:], columns=result_list_sampleData[0])
# 將 採樣的5個樣例值寫入後面

# 不必定有10000條數據
    樣例數據條數 = len(result_list_sampleData)-1
    列數量 = len(result_list_sampleData[0])

    for column_number in range(0, 列數量):
        #獲取到table_name 及string_column_name 對應的行號
        string_column_name = result_list_sampleData[0][column_number]
        index_number = result_list_schemaDetail_pdf[
            (result_list_schemaDetail_pdf['TABLE_NAME'] == table_name) & (
                result_list_schemaDetail_pdf['COLUMN_NAME'] == string_column_name)].index
        # 計算該column 的缺失值比例
        缺失值比例_dict = dict(result_list_sampleData_pdf.isnull().sum() / 樣例數據條數)
        result_list_schemaDetail_pdf.loc[index_number,
                                         '缺失值比例'] = 缺失值比例_dict[string_column_name]
        if 樣例數據條數 > 5:
            int_sample = 5
        else:
            int_sample = 樣例數據條數

        for x in range(1, int_sample+1):
        #對該 column 進行數據採樣,並寫入pandas 對應位置
            str_sample_data_column_name = 'sample_data' + str(x)
            sample_data_column_value = result_list_sampleData[x][column_number]
            result_list_schemaDetail_pdf.loc[index_number,
                                         str_sample_data_column_name] = sample_data_column_value

最後一步寫入excel ,結合excel 的一些篩選統計工做,咱們可讓協助的業務部門,架構部門也更好的瞭解整個合做夥伴的數據
在這裏插入圖片描述
代碼以下:使用前記得安裝

conda install openpyxl
# pandas to excel 因爲是第三方庫,寫的時候可能報錯,如
# "'utf8' codec can't decode byte 0xe9 in position 1: invalid continuation byte"
# 因此通常強制,字符集寫成 utf-8

writer = pd.ExcelWriter('output_test.xlsx')

result_list_schemaDetail_pdf.to_excel(writer, 'schema')
writer.save()

8.python missingno 缺失值可視化分析

主要用到missingno 對缺失值進行可視化分析,what is missingno
missingno provides a small toolset of flexible and easy-to-use missing data visualizations and utilities that allows you to get a quick visual summary of the completeness (or lack thereof) of your dataset.

github 連接:https://github.com/ResidentMario/missingno

對於咱們的測試庫, 如下代碼運行在jupyter notebook 中

test_oracle_obj = OracleBaseTool.OracleBaseTool('c##test','test','127.0.0.1','orcl')

sql_string = '''select * from EMP'''
result_list = test_oracle_obj.selectFromDbTable_WithTableHead(sql_string)

%matplotlib inline
import missingno
pdf = pd.DataFrame(result_list[1:], columns = result_list[0] )
missingno.matrix(pdf, labels=True)

柱狀圖分析,該圖按照數據排序,可視化了數據空缺的空間視圖。
在這裏插入圖片描述
條形圖, 該圖展示缺失值數量對比狀況。

missingno.bar(pdf)

在這裏插入圖片描述
缺失值的相關性分析,既 一個變量的缺失和另外一個變量 的關係,因爲咱們的樣例數據較少,因此效果不明顯,咱們同時看一個官網的例子。

missingno.heatmap(pdf)

在這裏插入圖片描述
在這裏插入圖片描述

缺失值的層次聚類分析,內在邏輯和上面相似,不過是用了不一樣的算法及展示形式。

missingno.dendrogram(pdf)

在這裏插入圖片描述

本文同步分享在 博客「shiter」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索