害!兩小時帶你看透python數據可視化

數據可視化筆記

一、數據可視化概述

1、什麼是數據可視化

在計算機視覺領域,數據可視化是對數據的一種形象直觀的解釋,實現從不同維度觀察數據,從而得到更有價值的信息。

  • 抽象的、複雜的、不易理解的數據

  • 圖形、圖像、符號、顏色、紋理等

  • 具備較高的識別效率

  • 數據本身所包含的有用信息

2、爲什麼要進行數據可視化

  1. 我們利用視覺獲取的信息量,遠遠比別的感官要多得多

  2. 數據可視化能夠幫助我們對數據有更加全面的認識

  3. 數據可視化能夠在小空間中展示大規模數據

3、案例展示

1)電影臺詞含義可視化

img

2)南丁格爾圖

img

3)文字和可視化對比效果

img

4、數據可視化的作用

  1. 記錄信息
    • img
    • img
  1. 分析推理
    • img
    • img
  1. 信息傳播與協同
    • img
    • img

5、數據可視化分類

1)科學可視化

面向科學和工程領域,如何以幾何、拓撲和形狀特徵來呈現數據中蘊含的規律

顏色映射

img

輪廓法

將數值等於某一指定指定閾值的點連接起來的可視化方法

img

2)信息可視化

是結構化、非幾何的數據如何從大規模高維複雜數據中提取出有用信息

地理信息

  • 空間數據:地理信息數據
    img

時變數據

  • 時變數據可視化採用多視角、數據比較等方法體現數據隨時間變化的趨勢和規律
    img

層次數據

img

網絡數據

  • 不具備層次結構,結構更加複雜自由
    img

DBSCAN
算法將數據點分爲三類:
核心 點:在半徑 Eps 內含有超過 MinPts 數目的 點
邊界點:在半徑 Eps 內點的數量小於 MinPts ,但是落在覈心點的鄰域 內
噪音點:既不是核心點也不是邊界點的點

img

6、數據可視化發展歷史與未來

1)數據可視化發展史

  1. 17世紀之前:圖表萌芽
    • 幾何圖表和地圖
    • 展示重要信息
  1. 1600-1699年:物理測量
    • 時間、距離、空間
    • 測量理論與設備的完善
  1. 1700-1799年:圖形符號
    • 等值線
    • 輪廓線
    • 折線圖
    • 柱狀圖
    • 餅狀圖
  1. 1800-1900年:數據圖形
    • 柱狀圖
    • 餅圖
    • 直方圖
    • 折線圖
  1. 1900-1949年:現代啓蒙
    • 廣泛應用於政府、商業和科學
    • 提供新的洞察和發現機會
    • 多維數據可視化和心理學介入
  1. 1950-1974年:多維信息的可視編碼
    • 《圖形符號學》,構成圖形的基本要素和圖形設計的框架
  1. 1975-1974年:多維統計圖形
    • 網絡、層次、數據庫、文本等非結構化與高維數據
    • 信息可視化發展成一門學科
  1. 1987-2004年:交互可視化
    • 實時數據可視化系統
  1. 2004年至今:可視分析學
    • 數據分析至關重要
    • 輔助用戶挖掘出有用信息,做出決策

2)數據可視化的未來

  1. 數據可視化面臨的挑戰
    • 數據規模大
    • 數據質量問題
    • 數據快速動態變化
    • 分析能力不足
    • 多來源數據的類型和結構各異
  1. 數據可視化發展方向
    • 可視化技術與數據挖掘有着緊密的聯繫
    • 可視化技術與人機交互有着緊密的聯繫

二、數據可視化理論

1、視覺感知

1)視覺感知和視覺認知

  1. 視覺感知和視覺認知
    • 視覺感知
      • 人類大腦的最主要功能之一
      • 人眼對客觀事物的第一映象
      • 在我們的生活中起着至關重要的作用
    • 視覺感知是指客觀事物通過人的視覺器官在人腦中形成的直接反映
      • 視覺低級
        • 與物體性質相關:深度、形狀、邊界、表面材質等
      • 視覺高級
        • 對物體的識別和分類
        • 一種基本的認知能力
      • 對所觀察到的客觀事物更深入的理解和解釋
      • 會受到記憶、理解、判斷、推理等因素的影
  1. 格式塔原則(完圖法則)
    • 基本準則
      • 描述了人在視覺上如何感知對象,是圖形和用戶界面你設計的基本準則
    • 視覺感知
      • 將視覺感知內容理解爲常規的、簡單的、相連的、對稱的或有序的結構
    • 簡單提煉法則
      • 是格式塔原則最基本的呢法則
    • 整體
      • 將事務理解爲一個整體,而不是將事務理解爲組成該事務所有部分的集合
    • 接近原則
      • 通常,人在進行視覺感知時會把距離上相互靠近的元素視作一個整體
      • 元素之間的距離越近,被視作組合的概率越大
    • 相似原則
      • 相似原則關注的是元素內部特徵的差異性,比如:紋理、顏色、形狀、大小等特徵
      • 人們的視覺感知常常會把具有明顯共同特徵的元素當成一個整體或歸爲一類
    • 閉合原則
      • 是指人們常常會儘可能地在心理上把一個不連貫的圖形補充完整,使之連貫,或者說傾向於從視覺上封閉那些開放或未完成的輪廓
    • 連續原則
    • 基本思想
      • 視覺形象是作爲一個統一的整體最先被認知的,而後纔是從各個部分開始認知
    • 數據可視化時將數據映射爲圖形元素,生成包含原始信息的視覺圖像的過程

2)顏色理論

  1. 三基色
    img
    • 三基色
    • 相加混色
    • 相加二次色
    • 補色
    • 中間色
  1. 色彩三要素
    img
    • 色相
    • 明度
    • 飽和度
  1. 色彩與心理
    img
    • 冷色
    • 暖色

3)可視化編碼

  1. 數據可視化的製作過程實質上是數據到視覺元素的編碼過程

  2. 可視化將數據以一定的編碼原則映射爲直觀、易於理解和記憶的可視化元素

  3. 爲了能有效、正確地引導用戶對數據的理解和分析,設計者在數據的可視化過程中必須遵循科學的可視化編碼原則

  4. 設計者要研究人的視覺感知、不同的可視化元素的展示效果,以及如何合理使用不同的視覺通道表達數據所傳達的重要信息,避免給用戶造成視覺錯覺,以達到良好的數據可視化效果。

  • 可視化編碼
    描述數據與可視化結果的映射關係,把可視化看做成一組符號的組合,這些圖形符號中攜帶了被編碼的信息,從這些符號中讀取相應的信息時,就稱之爲解碼

    • 標記
      • 是一組幾何圖形元素:如點、線、面、體等
    • 視覺通道
      • 用於控制標記的視覺特徵,常用的視覺通道有標記的顏色、位置、尺寸、形狀、方向、色相、明度、飽和度、紋理等

2、大數據技術

1)數據採集與預處理

  1. 數據來源
    • 人所產生的數據
    • 機器、設備和物體的數據
    • 行業、科研實驗數據
  1. 數據採集方法
    • 系統日誌
      • 網站點擊率、網頁瀏覽痕跡等
    • 網頁數據
      • 推文、評論、新聞信息等
    • 其他數據
      • 隱私數據、醫療、科學等
  1. 數據預處理

2)大數據存儲與管理

  1. 數據類型
    結構化數據
    • 保存在數據庫中
      • 關係型數據庫、非關係型數據庫

非結構化數據

    • 文本、圖片、音頻、視頻文件等
      • 分佈式文件系統

半結構化數據

    • xml文件、json文件、計算機日誌信息等
      • 用自定義的結構來存儲數據
  1. 數據存儲方式
    分佈式文件系統
    • 90%的大數據都是非結構化數據
    • 分佈式文件系統把一個文件分割成很多小的數據塊,分佈地存儲到多個計算機節點上
    • 爲了保證系統的容錯性和可靠性,分佈式文件系統採用多副本方式對數據塊進行冗餘存儲
      • 多副本容錯技術
        img

關係型數據庫

    • 保存小規模結構化數據

非關係型數據庫

    • 靈活的可擴展性
    • 分佈式特性與雲存儲緊密融合
    • 保存大規模數據
    • 開源,成本低

半結構化數據

    • 保存自定義結構的數據

雲存儲

    • 海量存儲,彈性伸縮,無縫擴展
      • 增加存儲節點,數據自動重組
      • 減少存儲節點,數據自動恢復
    • 高併發讀寫性能,擺脫單臺設備能力束縛
    • 高可靠性,系統業務不中斷
    • 同意訪問入口,多用戶並行訪問
    • 高可用性,由及時維護變爲定期維護

3)大數據分析與挖掘

大數據處理的數據類型

  1. 靜態數據

  2. 動態數據

大數據計算框架

  1. 批處理
    • 靜態數據
    • 高延遲
    • 歷史數據
  1. 流式處理
    • 動態數據
    • 低延遲
    • 實時性要求高
  1. 交互式查詢
    • 低延遲
    • 歷史數據
  1. MapReduce
    • 對靜態數據做批處理計算
  1. Spark
    • 對動態數據做流式處理
    • 交互式查詢

數據挖掘

4)大數據可視化

  • img

3、數據可視化基本圖表

  1. 柱狀圖
    • 柱狀對比圖
    • 堆疊柱形圖
    • 瀑布圖
  1. 條形圖
    • 雙向條形圖
    • 多維度雙向條形圖
    • 子彈圖
  1. 折線圖
    • 折線對比圖
    • 面積圖
    • 堆疊面積圖
  1. 餅圖
    • 環形圖
    • 嵌套環形圖
    • 南丁格爾玫瑰圖
  1. 直方圖

  2. 散點圖

  3. 氣泡圖

  4. 雷達圖

  5. 地圖

  6. 熱力圖

  7. 箱線圖

  8. 矩形樹圖

4、數據可視化工具

數據可視化工具特性

  • 實時性

    • 數據可視化工具必須適應大數據時代數據量的爆炸式增長需求
    • 必須快速蒐集和分析數據,並對數據信息進行實時更新
  • 更豐富的展現

    • 數據可視化工具需要具備更豐富的展現方式
    • 能充分滿足數據展現的多維度要求
  • 簡單操作

    • 數據可視化工具滿足快速發展,易於操作的特性
    • 能滿足互聯網時代信息多變的特點
  • 多種數據集成支持方式

    • 數據的來源不僅僅侷限於數據庫
    • 數據可視化工具將支持團隊協作數據、數據倉庫、文本等多種方式、並能夠通過互聯網進行展現

大數據可視化工具

  • 入門級工具

    • Excel是日常數據分析工作中最常用的工具,簡單易用,用戶不需要複雜的學習就可以輕鬆使用Excel提供的各種圖表功能,尤其是製作折線圖、餅狀圖、柱狀圖、散點圖等各種統計圖表時,Excel是普通用戶的首選工具
    • 信息圖表是信息、數據知識等的視覺化表達,它利用了人們對於文字信息更容易理解的特點,更高效、直觀、清晰地傳遞信息,在計算機科學、數學以及統計學領域有着廣泛的應用
    • 地圖工具在數據可視化中較爲常見,他在展示數據基於空間或地理上有着很強的表現力,可以直觀地展現各分析指標的分佈、區域等特徵
    • R、D3、Python
  • 信息圖表工具

    • google chart API:谷歌圖表API
    • Tableau:視覺創建和儀表板設計
    • Visual.ly:視覺內容
  • 地圖工具

    • Google Fushion Tables:雲計算的雛形
      • Google Fushion Tables讓一般使用者也可以輕鬆製作出專業的統計地圖,該工具可以讓數據表呈現爲圖表、圖形和地圖,從而幫助發現一些隱藏在數據背後的模式和趨勢
    • Modest Maps:交互地圖庫
      • Modest Maps是一個小型、可擴展、交互式的免費庫,提供了一套查看衛星地圖的API,只有10KB大小,是目前最小的可用地圖庫,特也是一個開源項目,有強大的社區支持,是在網站中整合地圖應用的理想選擇
    • Leaflet:互動地圖
      • Leaflet是一個小型化的地圖框架,通過小型化和輕量化來滿足移動網頁的需要
  • 高級分析工具

    • R是一個自由、免費、源代碼開放的軟件,它是一個用於統計計算和統計製圖的優秀工具,使用難度較高,通常用於大數據集的統計與分析
    • Python具有豐富和強大的繪圖庫
      • Seabron
      • Matplotlib
      • Pyecharts
      • Ggplot
    • D3是用來做web頁面可視化的組件,比較難入門,需要有HTML和JavaScript基礎才行,對JavaScript的DOM(文檔對象模型)要求也有點高

三、Numpy庫

1、數組、Numpy

1)數組

  • 一維的數據稱爲向量

    • 集合
      • 集合中的元素不要求是相同的類型
    • 元組
      • 元組中的元素也不要求是相同的類型
    • 列表
      • 列表中的元素可以是不同的類型
    • 一維數組
      • 數據會將輸入的數據轉換爲一致的數據類型
      • 數組計算的速度較其他類型都快
  • 二維的數據稱爲矩陣

    • 矩陣
    • 多組一維數據組合就是二維數據
    • 數據庫表格和Excel表格是最常見的二維數據
    • 嵌套的列表
    • 二維數組
    • DataFrame表格形式
  • 三維或者更高維的數據,可用數組來表示

    • 3維數據使用三層嵌套列表
    • 三維數組
  • 數組也可以表示一維數據、二維數據、對應的就是一維數組、二維數組

    • 大數據的開發流程一般包括:數據收集、數據存儲、數據分析和數據可視化
    • 結果數據一般都是結構化的二維數據、在對其進行數據可視化展現

2)Numpy

  • 具有一個強大的N維數組對象ndarray

  • 廣播函數功能

  • 具有線性代數、博立葉變換、隨機數生成等功能

  • 是Scipy、Pandas等數據處理或科學計算庫的基礎

  • 能夠整合C/C++/Fortran的代碼

Numpy使用array()提供數組的類型ndarray、Numpy的ndarray類型與python內置的list類型比較

  • 數組對象是一維數據更像單個數據,可以不使用for循環進行元素遍歷計算

  • Numpy一堆數據對象做了優化,計算速度更快,效率更高

  • 科學計算中,一維數組中的元素類型往往相同

  • 數組對象採用相同的數據類型,有助於節省運算和存儲空間

# 用列表存儲數據,並計算這組數據的平方
a = [1,2,3,4]
c = []
for i in a:
    c.append(i**2)
print(c)

# 用ndarray類型來存儲,計算顯然更加加單
# ndarray具有廣播功能
import numpy as np
a = np.array([1,2,3,4])
a**2

img

# Python原生數據類型與numpy數組性能對比
def add(n):
    a = []
    b = []
    c = []
    for i in range(n):
        a.append(i ** 2)
        b.append(i + 3)
        c.append(a[i] + b[i])
    return c

def np_add(n):
    a = np.arange(n) ** 2
    b = np.arange(n) + 3
    c = a + b
    return c

N = 1000000
# 比較性能,使用“魔法函數” timeit
%timeit add(N)
%timeit np_add(N)
# 使用numpy運行時間是使用列表的70分之一

img

2、ndarray的創建和操作

ndarray是一個多維數組對象,由兩部分構成

  • 實際的數據

  • 描述這些數據的元數據,即數據維度和數據類型等

同構

  • 所有元素的類型一般都是相同的
a = np.array([[1,'a', 3], [4,'v', 6]])
print(type(a))
a

img

1)ndarray的基本屬性

ndarray對象的屬性

一對象名稱.屬性名稱()

array([['1', 'a', '3'],
       ['4', 'v', '6']], dtype='<U11')
屬性 含義 結果 案例
a.shape 數據維度 (2, 3) 2行3列的二維數組
a.size 元素個數 6 6個元素
a.ndim 數組的維度 2 2維數組
a.dtype 元素的數據類型 dtype(‘int32’) dtype(‘int32’)
a.itemsize 每個元素的大小 以字節爲單位 4 int32爲四個字節

2)ndarray的元素類型

創建ndarray數組時可指定元素的數據類型

所支持的數據類型包括整數、浮點數、複數、布爾值、字符串或是普通的Python對象(object)

np.array([[1, 2, 3], [4, 5, 6]], dtype = np.float32)

img

array_01 = np.array([[1, 2, 3], [4, 5, 6]])
array_01.dtype

img

數據類型 類型說明 說明
int_ 默認整形
intc 等價於long的整形
int8 i1 字節整形,1個字節,範圍: [-128, 127]
int16 i2 整形,2個字節,範圍:[-32768, 32767]
int32 i3 整形,4個字節,範圍:[-2^31, 2^31 - 1]
int64 i4 整形,8個字節,範圍:[-2^63, 2^63 - 1]
uint8 u1 無符號整形,1個字節,範圍:[0, 255]
uint16 u2 無符號整形,2個字節,範圍:[0, 65535]
uint32 u3 無符號整形,1個字節,範圍:[0, 2^32 - 1]
uint64 u4 無符號整形,1個字節,範圍:[0, 2^64 - 1]
bool_ 以一個字節形成存儲的布爾值(True或是False)
float_ float64簡寫形式
float16 f2 半精度浮點型(2字節): 1符號位 + 5位指數 + 10位的小數部分
float32 f4或f 單精度浮點型(4字節): 1符號位 + 8位指數 + 23位小數部分
float64 f8或d 雙精度浮點型(8字節): 1符號位 + 11位指數 + 52位的小數部分
complex_ c16 complex128的簡寫形式
complex64 c8 複數,由兩個32位的浮點數來表示
complex128 c16 複數,由兩個64位的浮點數來表示
object O Python對象類型
String_ S 固定長度的字符串類型(每個字符1個字節),比如: 要創建一個長度爲8的字符串,應使用S8
Unicode_ U 固定長度的unicode類型的字符串(每個字符佔用字節數由平臺決定),長度定義類似String_類型

Python內建數據類型僅支持整數、浮點數和複數3種類型

對元素類型進行精確定義,有助於Numpy合理使用存儲空間並優化性能。

在科學計算和數據分析領域設計數據類型較多,對存儲和性能都有較高要求,並可以應對較大的數據應用場景。

非同質的ndarray對象

  • 非同質ndarray元素爲對象類型

  • ndarray數組可以由非同質對象構成

  • 非同質的ndarray對象的元素長度不同

  • 非同質ndarray對象無法有效發揮NumPy優勢,應該儘量避免使用

3)ndarray的創建

使用Python的列表、元組等類型創建ndarray數組
# 從列表創建
np.array([[1, 2, 3], [4, 5, 6]], dtype = np.float32)

img

# 從元組創建
np.array([(1, 2), (2, 3)])

img

# 從列表和元組創建
np.array([[1, 2, 3, 4], (4, 5, 6, 7)])

img

到這裏可以看出來,不管是什麼方式創建,最後都會轉化成列表類型

使用Numpy中的函數創建ndarray數組

# 類似range()函數,返回ndarray類型,元素從0到n - 1
np.arange(5)

img

# 根據shape生成一個全1數組,shape是元組類型
np.ones((3, 4))

img

# 根據shape生成一個全0數組,shape是元組類型
np.zeros((2, 3 ,4))

img

# 根據shape生成一個數組,每個元素都是val
np.full((2, 3), 99)

img

# 創建一個正方的n*n單位矩陣,對角線爲1,其餘爲0
np.eye(5)

img

# 根據已有數組,生成一個維度相同的新數組
print('array_01:\n', array_01)
# 根據數組array_01的形狀生成一個全1數組
print('np.ones_like:\n', np.ones_like(array_01))
# 根據數組array_01的形狀生成一個全0數組
print('np.zeros_like:\n', np.zeros_like(array_01))
# 根據數組array_01的形狀生成一個數組,每個元素值都是val
print('np.full_like:\n', np.full_like(array_01, 99))

img

# 根據起止數據等間距地填充數據,形成數組
np.linspace(1, 10, 10)

img

4)ndarray的變換

  • 維度變換

    • # 創建一個新的數組
      a = np.linspace(1, 12, 12, dtype=np.int32)
      # ndarray數組的維度變換
      # 不改變數組元素,返回一個shape形狀的數組,原數組a不變
      b = a.reshape(3, 4)
      print('a:\n', a)
      print('b:\n', b)
      

      img

    • # 改變數組的shape,且修改原數據
      a.resize(3, 4)
      a
      

      img

    • # 將數組n個維度中兩個維度進行調換
      a.swapaxes(1, 0)
      

      img

    • # 把數組的維度降低,返回摺疊後的一維數組,原數組不變
      a.flatten()
      

      img

  • 元素類型變換

    • # 創建一個新的數組
      b = np.linspace(1, 9, 9)
      b.resize(3, 3)
      print('b:\n', b)
      print('b.dtype:\n', b.dtype)
      d = b.astype(np.int16)
      print('d:\n', d)
      

      img

  • 數組轉換爲列表

    • print('b:\n', b)
      # 轉換爲list類型
      b.tolist()
      

      img

5)ndarray的操作

索引:獲取數組中特定位置的元素

維度用,切開 不用,表示一個維度一直用行,先從行開始 :後面不包括

c = np.linspace(1, 24, 24, dtype=np.int)
c.resize(2, 3, 4)
print('c:\n', c)
print('c[0]:\n', c[0])
print('c[0][0]:\n', c[0][0])
# 多維數組索引方式一
print('c[0][0][0]:\n', c[0][0][0])
# 多維數組索引方式二
print('c[0, 0, 0]:\n', c[0, 0, 0])

img

切片:獲取數組元素子集

# 切片獲取元素子集
print('c:\n', c)
print('c[0][1:3][1:3]:\n', c[0][1:3][1:3])
print('c[0, 1:3, 1:3]:\n', c[0, 1:3, 1:3])
# 獲取步長跳躍切片
print('c[0, 1, ::2]:\n', c[0, 1, ::2])#雙冒號表示步長

img

3、ndarray數組的運算

1)ndarray與標量運算

  • 乘法

    # 乘法
    a = np.arange(1, 10).reshape(3, 3)
    b = [1, 2, 4]
    print('a:\n', a)
    print('a*10:\n', a*10)
    print('b*3:\n', b*3)
    

    img

  • 平方

    # 平方
    a**2
    

    img

  • 減法

    # 減法
    a - 9
    

    img

  • 邏輯運算、比較大小、過濾元素

    # 數組的重要特性,過濾值
    print('a > 5:\n', a > 5)
    # 使用多條條件過濾,注意運算優先級
    print('a[(a > 5) & (a < 8)]:\n', a[(a > 5) & (a < 8)])
    

    img

2)數組元素運算函數

函數名稱 函數功能
np.abs(b) 計算各元素的絕對值
np.sqrt(b) 計算各元素的平方根
np.square(b) 計算各元素的平方
np.log(b)、np.log10(b)、np.log2(b) 計算數組各元素的自然對數、10底對數和2底對數
np.ceil© 計算數組各元素的ceiling值,向上取整
np.floor© 計算數組各元素的floor值,向下取整
np.rint© 計算數組各元素的四捨五入值
np.modf© 將數組個元素的小樹和整數部分以兩個獨立數組形式返回
np.cos© 三角函數

3)數組間的運算

維度相同的數組

  • 加:a + b

  • 減:a - b

  • 乘:a * b

  • 除:a / b

  • 邏輯運算:a > b

4)Numpy統計函數

數組內的所有元素進行統計,通常是返回一個數值

  • np.sum()求和

    # 求每列的和
    print('np.sum(a, axis=0):\n', np.sum(a, axis=0))
    # 求每行的和
    print('np.sum(a, axis=1):\n', np.sum(a, axis=1))
    # 求所有元素的和
    print('np.sum(a):\n', np.sum(a))
    

    img

函數名稱 函數功能
np.min(a) 求取最小值
np.max(a) 求取最大值
np.median(a) 計算中間值
np.average(a) 計算加權平均值
np.mean(a) 計算算術平均值
np.std(a) 計算標準差
np.var(a) 計算方差

四、Pandas庫

1、Pandas數據結構Series對象

1)創建Series對象

Series保存的是一維帶索引的數組

數組中的元素可以是任何數據類型,整數,字符串,浮點數,Python對象等

  • data,一維數組

    • Numpy的ndarray對象
    • 字典、列表等
    • 一個數值,比如數字5
  • Index,每個元素的索引

    • Series一維數組的每個元素都帶有索引
    • 如果不傳入index參數,會自動爲每個元素生產索引
# 導入pandas和numpy
import pandas as pd
import numpy as np
data = np.arange(1, 10)
index = np.arange(11, 20)
s = pd.Series(data, index=index)
s

img

  • 從Numpy的ndarray對象創建Series對象

    • 如果傳入的data是一個ndarray對象,索引index必須和data要有一樣的長度
    • 如果沒有傳入索引index,將會自動創建一個從0開始的索引
    • 傳入index索引

      s = pd.Series(np.random.rand(5), index=['a', 'b', 'c','d', 'e'])
      
    • 不傳入index索引,自動創建索引

s = pd.Series(np.random.rand(5))

  • 用字典創建Series對象

    • 如果不傳入索引

      index

      參數,字典的key將會成爲索引


    d = {'a': 1, 'b': 3, 'c': 5}
    pd.Series(d)

  
- - 如果傳入的data是dict類型,並且同時傳入了索引index,則將按照傳入的索引值來創建Series對象

- - 如果傳入的索引

    index

    與傳入的數據

    data

    不匹配,則將以索引爲準。

    ```
    pd.Series(d, index=['a', 'b', 'c', 'd', 'e'])
    ```


- 用列表創建Series對象

- - 如果不傳入索引,則會自動創建索引

    ```
    pd.Series([x for x in range(1, 5)])
    ```


- - 如果傳入索引,索引的長度必須與

    data

    的長度相同

    ```
    pd.Series([x for x in range(1, 5)], list('abcd'))
    ```



- - 如果索引的長度與data的長度不同,程序會報錯





#### 2)操作Series對象



- 數字索引

- index

  索引

  ```python
  s = pd.Series(np.random.rand(3), index=['a', 'b', 'c'])
  print("s[0]:\n", s[0])
  print("s['b']:\n", s['b'])

img

判斷索引是否在索引列表中

  • In

  • 直接訪問一個不存在的索引會報KeyError錯誤

  • get函數

    • 索引存在,則返回對應值
    • 索引不在,無返回值
    • 指定索引不存在的的返回值
print("'a' in s: \n", 'a' in s)
print("'f' in s: \n", 'f' in s)
try:
    print("s['f']: \n", s['f'])
except KeyError:
    print(KeyError)
print("s.get('b'): \n", s.get('b'))
print("s.get('f'):\n", s.get('f'))
print("s.get('f', 'f不在索引列表中'):\n", s.get('f', 'f不在索引列表中'))

img

切片

  • 分號分隔,截取部分子集

    print("s[:3]:\n{}".format(s[:3]))
    print("s[:'c']:\n{}".format(s[:'c']))
    print("s[1:3]:\n{}".format(s[1:3]))
    print("s[[1,2]]:\n{}".format(s[[1,2]]))
    

    img

跟ndarray類似

  • 進行向量化計算

    • 加減乘除
  • numpy的很多函數也能夠作用於Series對象

    • np.sqrt(s),np.square(s)

3)時間序列

  • Series對象最重要的功能是保存和處理時間序列數據

  • 金融領域的數據一般都是時間序列數據

  • Pandas能夠很好地支持時間序列數據

  • pandas的data_range函數創建一個時間序列

    # 生成從2018年9月1日開始,十天的時間序列索引,頻率爲10分鐘
    rng = pd.date_range('9/1/2018', periods=1440, freq='10Min')
    rng[:5]
    

    img

  • 創建Series對象,對應索引爲時間序列

    ts = pd.Series(np.random.rand(1440), index=rng)
    ts.head()
    

    img

    ts.count()
    

    img

  • 切片的方式提取和訪問數據

    ts[:5]
    

    img

    ts[:10:2]
    

    img

  • 時間日期與切片結合的方式提取數據

    # 時間字符串索引
    ts['9/6/2018'][140:]
    

    img

    # datetime類型的索引
    from datetime import datetime
    ts[datetime(2018, 9, 9):][::60]
    

    img

2、DataFrame對象的創建與保存

1)創建DataFrame對象

  • DataFrame是一種帶索引的二維數據結構

  • 二維數據

    • 二維列表
    • ndarray對象
  • 一維數據

    • 一維列表
      • 多個一維列表要求長度相同
      • 組成一個字典
    • Series對象
      • 組成一個字典
  • 包含字典的列表

  • 三維數據

    • 可傳入三維列表數據,但無法解析
    • 不能傳入ndarray三維數組

2)保存到文件數據庫

DataFrame數據導出到文件

  • Tushare是一個免費、開源的python財經數據接口包

  • Tushare返回的絕大部分的數據格式都是pandas DataFrame類型,非常便於用pandas進行數據分析

  • 安裝:pip install tushare

  • 官方文檔:http://tushare.org/
    img
    img
    img

  • 導出到MySQL數據庫
    img

3)讀取文件/數據庫

  • 讀取Excel、json文件

    • read_excel()讀取Excel文件數據
    • Excel文件可以是包含單個表的文件
    • Excel也可以是包含多個表的工作薄,這時需要指定工作表名稱
    • read_json()讀取json文件內容
  • 讀取數據庫table內的表

    • 建立數據庫連接
    • read_sql()讀取指定表的內容

3、DataFrame的數據操作

  • 選擇、添加與刪除數據

    • 選擇行和列
    • 添加新列
      • 基於已有列添加新列
      • 用標量賦值
      • Series對象
      • 指定列插入
    • 刪除列
      • pop()刪除指定列,返回指定列
      • del 刪除指定列,無返回值
  • 分組計算與彙總

    • 導入數據
    • 按照條件對所有的數值型變量進行彙總
      • 分組:groupby()
      • 彙總:sum()
    • 選擇有現實意義的數值型變量進行彙總
      • 添加變量的索引進行彙總
    • 分組彙總單列數據
    • mean()求平均值
    • describe()進行描述性統計
    • 多個分類變量對數據進行彙總
  • 數據融合

    • merge()基於指定列進行連接

      df1 = pd.DataFrame({'name': ['hellof', 'masonsxu', 'a', 'b', 'c']})
      df2 = pd.DataFrame({'name': ['hellof', 'masonsxu', 'A', 'B', 'C']})
      pd.merge(df1, df2, on='name')
      

      img

    • inner內連接

      pd.merge(df1, df2, how='inner')
      

      img

    • left左連接

      pd.merge(df1, df2, how='left')
      

      img

    • right右連接

      pd.merge(df1, df2, how='right')
      

      img

    • outer外連接

      pd.merge(df1, df2, how='outer')
      

      img

五、matplotlib庫

繪圖區域

image-20200411225454819

image-20200411225558991

這個地方我解釋一下,211,2兩個圖,1表示1列,最後一個1表示在上面,同理2表示在下面,所以有兩個圖

plot()函數

image-20200411225942663

例如

image-20200411230013557

image-20200411230130021

image-20200411230155350

image-20200411230211066

例如

image-20200411230229263

image-20200411230501429

中文顯示

image-20200411230538137

image-20200412104302882

image-20200412104500419

image-20200412104558747

image-20200412104618701

文本顯示

image-20200412110429706

image-20200412110445479

image-20200412110534874

子繪圖區域

image-20200412110654468

image-20200412111438481

image-20200412111525082

image-20200412112127674

六、Pyecharts庫

1.柱形圖

from pyecharts import Bar
# 數據
goods =["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"]
sales1 =[5, 20, 36, 10, 10, 100] # 商家A各個產品對應的銷售量
sales2 =[55, 60, 16, 20, 15, 80] # 商家B各個產品對應的銷售量

bar = Bar('柱形圖-銷售量', '顯示服裝的各個子類的銷售量')
bar.add('服裝', goods, sales1,  is_label_show=True) # is_label_show在柱形圖上方顯示銷售量
bar.render(path='results/1.柱形圖.html')

bar2 = Bar("顯示標記線和標記點")
bar2.add('商家A', goods, sales1, mark_point=['average']) # mark_point標記商家A與平均值最接近的銷售量
bar2.add('商家B', goods, sales2, mark_line=['min', 'max']) # mark_line標記商家B的銷售量最大值和最小值
bar2.render(path='results/2.標記點柱形圖.html')

bar3 = Bar("水平顯示")
bar3.add('商家A', goods, sales1)
bar3.add('商家B', goods, sales2, is_convert=True) # is_convert 交換 XY 軸
bar3.render(path='results/3.水平柱形圖.html')

image-20200415172809279

image-20200415172834359

image-20200415172846220

2. 柱形圖+datazoom_slider

import random
from pyecharts import Bar

days = ["{}天".format(i) for i in range(1,31)] # 橫座標爲每一天
sales1 = [random.randint(0, 100) for _ in range(1,31)] # 縱座標爲每一天的銷售量
bar = Bar("展示一個月每一天的銷售量","Bar_datazoom_slider 示例")
bar.add("", days, sales1, is_label_show=False, is_datazoom_show=True) # is_datazoom_show 顯示下方的滑動條
bar.render(path='results/4.datazoom_slider.html')

image-20200415173127641

3. 柱形圖+datazoom_inside

import random
from pyecharts import Bar

days = ["{}天".format(i) for i in range(1,31)]
sales1 = [random.randint(0, 100) for _ in range(1,31)]
bar = Bar("展示一個月每一天的銷售量","Bar_datazoom_inside 示例")
bar.add(
    "",
    days,
    sales1,
    is_datazoom_show=True,
    datazoom_type="both", # 取值可以"inside"或"both","inside"沒有下方的滑動條,但可以通過滑動鼠標滾輪控制顯示柱形圖個數。
    # "both"即顯示下方的滑動條,又可以用鼠標滾輪控制顯示個數。
    datazoom_range=[10, 25],
)
bar.render(path='results/5.datazoom_inside.html')

image-20200415173547365

4. 柱形圖+多個datazoom

import random
from pyecharts import Bar
days = ["{}天".format(i) for i in range(1,30)]
sales1 = [random.randint(0, 100) for _ in range(1,30)]
bar = Bar("展示一個月每一天的銷售量","Bar_datazoom_xaxis/yaxis 示例")
bar.add(
    "",
    days,
    sales1,
    # 默認爲 X 軸,橫向
    is_datazoom_show=True,
    datazoom_type="slider",
    datazoom_range=[10, 25],
    # 新增額外的 dataZoom 控制條,縱向
    is_datazoom_extra_show=True,
    datazoom_extra_type="slider",
    datazoom_extra_range=[10, 25],
    is_toolbox_show=False,
)
bar.render(path='results/6.datazoom_xaxis_yaxis.html')

image-20200415173723379

5. 座標軸標籤旋轉示例

import random
from pyecharts import Bar
days = ["第{}天".format(i) for i in range(1,31)]
sales1= [random.randint(0,100) for _ in range(1,31)]
bar = Bar("座標軸標籤旋轉示例")
bar.add("", days, sales1, xaxis_interval=0, xaxis_rotate=30, yaxis_rotate=20)
bar.render(path='results/7.座標軸標籤旋轉示例.html')

image-20200415173835380

6. 雙向條形圖

from pyecharts import Bar

months = ["{}月".format(i) for i in range(1, 8)]
cost = [1000.0, 150.0, 120.0, 130.0, 200.0, 150.0, 200.0]
income = [200.0, 300.0, 260.0, 300.0, 230.0, 180.0, 320.0]
bar = Bar("成本收入對比圖","雙向條形圖")
# 利用第一個 add() 圖例的顏色爲透明,即 'rgba(0,0,0,0)',並且設置 is_stack 標誌爲 True
bar.add("cost", months, cost,  is_label_show=True,is_stack=True, label_pos='inside')
bar.add("income", months, income, is_label_show=True, is_stack=True, label_pos='inside', is_convert=True)
bar.render(path='results/8.成本收入對比圖.html')

image-20200415174006516

7. 對比柱狀圖

from pyecharts import Bar

attr = ["{}月".format(i) for i in range(1, 13)]
v1 = [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
v2 = [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
bar = Bar("柱狀圖示例","副標題",extra_html_text_label=["額外的文本標籤", "color:red"])
bar.add("蒸發量", attr, v1, mark_line=["average"], mark_point=["max", "min"])
bar.add("降水量", attr, v2, mark_line=["average"], mark_point=["max", "min"])
bar.render(path='results/9.降水量與蒸發量.html')

image-20200415204647297

8. 3D 柱狀圖

from pyecharts import Bar3D
import pandas as pd
#假設我們的數據集是一個數據框。
#該數據集有三個維度,分別是month、city、sales。其中month、city是類別變量,sales是數值型變量。
data=pd.DataFrame({'month':['1月','2月','3月','1月','2月','3月'],
                   'city':['北京','北京','北京','上海','上海','上海'],
                   'sales':[400,500,430,550,600,420] })
#由於Bar3D處理的數據要求是列表型,這裏對數據框數據做一些處理。
#x,y軸表示類目軸,取值是獨立不重複的。
x_name = list(set(data.iloc[:, 0]))
y_name = list(set(data.iloc[:, 1]))

#將原始數據框數據轉換成列表型。
data_xyz=[]
for i in range(len(data)):
     x=x_name.index(data.iloc[i,0])
     y=y_name.index(data.iloc[i,1])
     z=data.iloc[i,2]
     data_xyz.append([x,y,z])
#注意:這裏將類別數據轉換成了數值數據,便於在x、y、z軸繪製出圖形。
#初始化圖形。
bar3d=Bar3D("1-3月各城市銷量","單位:萬件",title_pos="center",width=1200,height=800)
#隨機選取幾種顏色編碼用於區分
range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf',
               '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
#添加數據層,並配置圖形參數。
bar3d.add('', #''表示圖表標題爲空
x_name,y_name, #x_name、y_name是類別值
data_xyz,#data_xyz是處理後的數據
is_label_show=True,#is_label_show=True表示顯示數據標籤
is_visualmap=True, #是否以熱圖顯示
visual_range_color=range_color, #熱圖顏色範圍
visual_range=[0, 500],#visual_range調整數據顏色深度,這裏超過500的數值顏色更深
grid3d_shading='lambert',# 讓柱形圖看起來更加真實
is_grid3d_rotate=True, # 啓動自動旋轉功能
grid3d_rotate_speed=90, # 調節旋轉速度
grid3d_width=150, #柱形寬度
grid3d_depth=50)#柱形高度
bar3d.render(path='results/10.3D柱狀圖.html')

image-20200415205357695

9. 箱形圖

from pyecharts import Boxplot

boxplot = Boxplot("箱形圖")
x_axis = ['expr1', 'expr2', 'expr3', 'expr4', 'expr5']
y_axis = [
    [850, 740, 900, 1070, 930, 850, 950, 980, 980, 880,
    1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960],
    [960, 940, 960, 940, 880, 800, 850, 880, 900, 840,
    830, 790, 810, 880, 880, 830, 800, 790, 760, 800],
    [880, 880, 880, 860, 720, 720, 620, 860, 970, 950,
    880, 910, 850, 870, 840, 840, 850, 840, 840, 840],
    [890, 810, 810, 820, 800, 770, 760, 740, 750, 760,
    910, 920, 890, 860, 880, 720, 840, 850, 850, 780],
    [890, 840, 780, 810, 760, 810, 790, 810, 820, 850,
    870, 870, 810, 740, 810, 940, 950, 800, 810, 870]
]
_yaxis = boxplot.prepare_data(y_axis)       # 轉換數據
boxplot.add("boxplot", x_axis, _yaxis)
boxplot.render(path='results/11.箱型圖.html')

image-20200417104756684

10. 對比箱型圖

from pyecharts import Boxplot

boxplot = Boxplot("箱形圖")
x_axis = ['expr1', 'expr2']
y_axis1 = [
    [850, 740, 900, 1070, 930, 850, 950, 980, 980, 880,
    1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960],
    [960, 940, 960, 940, 880, 800, 850, 880, 900, 840,
    830, 790, 810, 880, 880, 830, 800, 790, 760, 800],
]
y_axis2 = [
    [890, 810, 810, 820, 800, 770, 760, 740, 750, 760,
    910, 920, 890, 860, 880, 720, 840, 850, 850, 780],
    [890, 840, 780, 810, 760, 810, 790, 810, 820, 850,
    870, 870, 810, 740, 810, 940, 950, 800, 810, 870]
]
boxplot.add("category1", x_axis, boxplot.prepare_data(y_axis1))
boxplot.add("category2", x_axis, boxplot.prepare_data(y_axis2))
boxplot.render(path='results/11.箱型圖2.html')

image-20200417104926208

11. 動態散點圖

from pyecharts import EffectScatter

v1 = [10, 20, 30, 40, 50, 60]
v2 = [25, 20, 15, 10, 60, 33]
es = EffectScatter("動態散點圖示例")
es.add("effectScatter", v1, v2)
es.render(path='results/12.動態散點圖.html')

image-20200417105046125

12. 動態散點圖2

from pyecharts import EffectScatter
es = EffectScatter("動態散點圖各種圖形示例")
es.add(
    "",
    [10],
    [10],
    symbol_size=20,
    effect_scale=3.5,
    effect_period=3,
    symbol="pin",
)
es.add(
    "",
    [20],
    [20],
    symbol_size=12,
    effect_scale=4.5,
    effect_period=4,
    symbol="rect",
)
es.add(
    "",
    [30],
    [30],
    symbol_size=30,
    effect_scale=5.5,
    effect_period=5,
    symbol="roundRect",
)
es.add(
    "",
    [40],
    [40],
    symbol_size=10,
    effect_scale=6.5,
    effect_brushtype="fill",
    symbol="diamond",
)
es.add(
    "",
    [50],
    [50],
    symbol_size=16,
    effect_scale=5.5,
    effect_period=3,
    symbol="arrow",
)
es.add(
    "",
    [60],
    [60],
    symbol_size=6,
    effect_scale=2.5,
    effect_period=10,
    symbol="triangle",
)
es.render(path='results/12.動態散點圖2.html')

image-20200417105212201

13. 地圖

from pyecharts import Geo

data = [
    ("海門", 9),("鄂爾多斯", 12),("招遠", 12),("舟山", 12),("齊齊哈爾", 14),("鹽城", 15),
    ("赤峯", 16),("青島", 18),("乳山", 18),("金昌", 19),("泉州", 21),("萊西", 21),
    ("日照", 21),("膠南", 22),("南通", 23),("拉薩", 24),("雲浮", 24),("梅州", 25),
    ("文登", 25),("上海", 25),("攀枝花", 25),("威海", 25),("承德", 25),("廈門", 26),
    ("汕尾", 26),("潮州", 26),("丹東", 27),("太倉", 27),("曲靖", 27),("煙臺", 28),
    ("福州", 29),("瓦房店", 30),("即墨", 30),("撫順", 31),("玉溪", 31),("張家口", 31),
    ("陽泉", 31),("萊州", 32),("湖州", 32),("汕頭", 32),("崑山", 33),("寧波", 33),
    ("湛江", 33),("揭陽", 34),("榮成", 34),("連雲港", 35),("葫蘆島", 35),("常熟", 36),
    ("東莞", 36),("河源", 36),("淮安", 36),("泰州", 36),("南寧", 37),("營口", 37),
    ("惠州", 37),("江陰", 37),("蓬萊", 37),("韶關", 38),("嘉峪關", 38),("廣州", 38),
    ("延安", 38),("太原", 39),("清遠", 39),("中山", 39),("昆明", 39),("壽光", 40),
    ("盤錦", 40),("長治", 41),("深圳", 41),("珠海", 42),("宿遷", 43),("咸陽", 43),
    ("銅川", 44),("平度", 44),("佛山", 44),("海口", 44),("江門", 45),("章丘", 45),
    ("肇慶", 46),("大連", 47),("臨汾", 47),("吳江", 47),("石嘴山", 49),("瀋陽", 50),
    ("蘇州", 50),("茂名", 50),("嘉興", 51),("長春", 51),("膠州", 52),("銀川", 52),
    ("張家港", 52),("三門峽", 53),("錦州", 54),("南昌", 54),("柳州", 54),("三亞", 54),
    ("自貢", 56),("吉林", 56),("陽江", 57),("瀘州", 57),("西寧", 57),("宜賓", 58),
    ("呼和浩特", 58),("成都", 58),("大同", 58),("鎮江", 59),("桂林", 59),("張家界", 59),
    ("宜興", 59),("北海", 60),("西安", 61),("金壇", 62),("東營", 62),("牡丹江", 63),
    ("遵義", 63),("紹興", 63),("揚州", 64),("常州", 64),("濰坊", 65),("重慶", 66),
    ("台州", 67),("南京", 67),("濱州", 70),("貴陽", 71),("無錫", 71),("本溪", 71),
    ("克拉瑪依", 72),("渭南", 72),("馬鞍山", 72),("寶雞", 72),("焦作", 75),("句容", 75),
    ("北京", 79),("徐州", 79),("衡水", 80),("包頭", 80),("綿陽", 80),("烏魯木齊", 84),
    ("棗莊", 84),("杭州", 84),("淄博", 85),("鞍山", 86),("溧陽", 86),("庫爾勒", 86),
    ("安陽", 90),("開封", 90),("濟南", 92),("德陽", 93),("溫州", 95),("九江", 96),
    ("邯鄲", 98),("臨安", 99),("蘭州", 99),("滄州", 100),("臨沂", 103),("南充", 104),
    ("天津", 105),("富陽", 106),("泰安", 112),("諸暨", 112),("鄭州", 113),("哈爾濱", 114),
    ("聊城", 116),("蕪湖", 117),("唐山", 119),("平頂山", 119),("邢臺", 119),("德州", 120),
    ("濟寧", 120),("荊州", 127),("宜昌", 130),("義烏", 132),("麗水", 133),("洛陽", 134),
    ("秦皇島", 136),("株洲", 143),("石家莊", 147),("萊蕪", 148),("常德", 152),("保定", 153),
    ("湘潭", 154),("金華", 157),("岳陽", 169),("長沙", 175),("衢州", 177),("廊坊", 193),
    ("菏澤", 194),("合肥", 229),("武漢", 273),("大慶", 279)]

geo = Geo(
    "全國主要城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    width=1200,
    height=600,
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add(
    "",
    attr,
    value,
    visual_range=[0, 200],
    visual_text_color="#fff",
    symbol_size=15,
    is_visualmap=True,
)
geo.render(path='./results/13.地圖1.html')

geo = Geo(
    "全國主要城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    width=1200,
    height=600,
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add(
    "",
    attr,
    value,
    visual_range=[0, 200],
    visual_text_color="#fff",
    symbol_size=15,
    is_visualmap=True,
    is_piecewise=True,
    visual_split_number=6,
)
geo.render(path='./results/13.地圖2.html')

geo = Geo(
    "全國主要城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    width=1200,
    height=600,
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add(
    "",
    attr,
    value,
    type="heatmap",
    is_visualmap=True,
    visual_range=[0, 300],
    visual_text_color="#fff",
)
geo.render(path='results/13.地圖3.html')

image-20200417110234668

image-20200417110313352

14.地圖2

from pyecharts import Geo

data = [
    ("海門", 9), ("鄂爾多斯", 12), ("招遠", 12), ("舟山", 12), ("齊齊哈爾", 14), ("鹽城", 15)
]
geo = Geo(
    "全國主要城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    width=1200,
    height=600,
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add("", attr, value, type="effectScatter", is_random=True, effect_scale=5)
geo.render(path='results/14.地圖1.html')

image-20200417110655612

15. 廣東空氣質量

from pyecharts import Geo

data = [("汕頭市", 50), ("汕尾市", 60), ("揭陽市", 35), ("陽江市", 44), ("肇慶市", 72)]
geo = Geo(
    "廣東城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    width=1200,
    height=600,
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add(
    "",
    attr,
    value,
    maptype="廣東",
    type="effectScatter",
    is_random=True,
    effect_scale=5,
    is_legend_show=True,
    
)
geo.render(path='results/15.廣東空氣質量.html')

image-20200417111143807

16.英國空氣質量

from pyecharts import Geo

data = [("Oxford", 15), ("London", 12)]

geo = Geo(
    "英國主要城市空氣質量",
    "data from pm2.5",
    title_color="#fff",
    title_pos="center",
    background_color="#404a59",
)
attr, value = geo.cast(data)
geo.add_coordinate('Oxford', 51.7520209,-1.2577263000000585)
geo.add_coordinate('London', 51.5073509,-0.12775829999998223)
geo.add(
    "",
    attr,
    value,
    maptype="英國",
    # 使用 coordinate_region,指定檢索英國範圍內的座標,如上述的 Oxford。
    # 默認爲中國
    coordinate_region="英國",
    visual_range=[0, 200],
    visual_text_color="#fff",
    symbol_size=15,
    is_visualmap=True,
)

geo.render(path='results/16.英國空氣質量.html')

image-20200417111719680

17. 地理座標系

from pyecharts import GeoLines, Style

style = Style(
    title_top="#fff",
    title_pos = "center",
    width=1200,
    height=600,
    background_color="#404a59"
)

data_guangzhou = [
    ["廣州", "上海"],
    ["廣州", "北京"],
    ["廣州", "南京"],
    ["廣州", "重慶"],
    ["廣州", "蘭州"],
    ["廣州", "杭州"]
]
geolines = GeoLines("GeoLines 示例", **style.init_style)
geolines.add("從廣州出發", data_guangzhou, is_legend_show=False)
geolines.render(path='results/17.地理座標.html')

image-20200417111704740

18. 關係圖

from pyecharts import Graph

nodes = [{"name": "結點1", "symbolSize": 10},
         {"name": "結點2", "symbolSize": 20},
         {"name": "結點3", "symbolSize": 30},
         {"name": "結點4", "symbolSize": 40},
         {"name": "結點5", "symbolSize": 50},
         {"name": "結點6", "symbolSize": 40},
         {"name": "結點7", "symbolSize": 30},
         {"name": "結點8", "symbolSize": 20}]
links = []
for i in nodes:
    for j in nodes:
        links.append({"source": i.get('name'), "target": j.get('name')})
graph = Graph("關係圖-力引導佈局示例")
graph.add("", nodes, links, repulsion=8000)
graph.render(path='results/18.關係圖.html')

image-20200419150909132

19. 微博轉發關係圖

from pyecharts import Graph
import os
import json
with open(os.path.join("data", "weibo-1.json"), "r", encoding="utf-8") as f:
    j = json.load(f)
    nodes, links, categories, cont, mid, userl = j
graph = Graph("微博轉發關係圖", width=1200, height=600)
graph.add(
    "",
    nodes,#節點
    links,#不同點之間連線
    categories,#分類
    label_pos="right",#標籤位置 右側
    graph_repulsion=50,#不同點之間斥力
    is_legend_show=False,#是否顯示圖例
    line_curve=0.2,#線條玩去程度
    label_text_color=None,#標籤文本顏色
)
graph.render(path='results/19.微博轉發關係圖.html')

image-20200419150807754

20. 廣東地圖

from pyecharts import Map

value = [20, 190, 253, 77, 65]
attr = ['汕頭市', '汕尾市', '揭陽市', '陽江市', '肇慶市']
map = Map("廣東地圖示例", width=1200, height=600)
map.add(
    "", attr, value, maptype="廣東", is_visualmap=True, visual_text_color="#000"
)
map.render(path='results/20.廣東地圖.html')

image-20200419152943825

21. 世界地圖

from pyecharts import Map
value = [95.1, 23.2, 43.3, 66.4, 88.5]
attr= ["China", "Canada", "Brazil", "Russia", "United States"]
map = Map("世界地圖示例", width=1200, height=600)
map.add(
    "",
    attr,
    value,
    maptype="world",
    is_visualmap=True,
    visual_text_color="#000",
)
map.render(path='results/21.世界地圖.html')

image-20200419152953650

七、時間數據可視化

1、連續型數據處理

階梯圖

階梯圖是曲線保持在同一個值,直到發生變化,直接跳躍到下一個值。它的形狀就類似於平時樓道里面的樓梯。比如說,銀行的利率,它一般會持續幾個月不變,然後某一天出現上調或下調。樓盤價格長時間停留在某個值,突然有一天因爲各種調控,出現調整。對於這類的數據類型就可以使用階梯圖

如何使用Python畫出階梯圖,這裏用的是pyecharts模塊,圖形3-3展示的就是最終的圖表。它表現的是美國郵政投遞信件的資費變化圖。注意一點,這裏的變化不是定期變化的。這裏可以看出1995-1999是4年沒發生變化,但是2006-2009就是每年漲一次。

代碼:

from pyecharts import Line
line = Line("美國郵票階梯圖")
datax=[1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009]
datay = [0.32,0.32,0.32,0.32,0.33,0.33,0.34,0.37,0.37,0.37,0.37,0.39,0.41,0.42,0.44]
line.add("Price",datax, datay, is_step=True,is_label_show=True,
yaxis_min=0.3,yaxis_max=0.45)
line.render()

image-20200411234927229

上述代碼功能是這樣的,事先數據準備,這裏用2個列表存儲數據datax存儲的事時間數據,datay存儲的是郵費數據。如果數據量大的話可以用文件存數據,下面3.2.2會涉及到,這裏就不加概述。最後用pyecharts. Line來畫這個梯形圖,另外如果將line.add()函數中的is_step去掉就是呈現的一個折線圖

折線圖

折線圖是用直線段將各數據點連接起來而組成的圖形,以折線方式顯示數據的變化趨勢。在時間數據中,折線圖的沿水平軸均勻分佈的是時間,沿垂直軸均勻分佈的是所有值數據。折線圖比較適用於趨勢類的需求。常用於,人口增長趨勢,書籍銷售量,粉絲增長進度等等

如何在python中創建時間序列的折線圖,這裏使用了畫圖包的裏的另一個matplotlib模塊,下面就舉例講解下。首先基礎數據的準備,這裏是從網站(http://datasets.flowingdata.com/world-population.csv)下載了一個每年世界人口的數據統計。然後載入數據

代碼:

import csv
import matplotlib.pyplot as plt
filename = "data/world-population.csv"
datax = []
datay = []
with open(filename) as f:
    reader = csv.reader(f)
    for datarow in reader:
        if reader.line_num != 1:
            print(reader.line_num,datarow)
            datax.append(datarow[0])
            datay.append(datarow[1])
plt.plot(datax,datay)
plt.show()

image-20200411171018213

擬合曲線

擬合曲線是根據所給定的離散數據點繪製的曲線,稱爲不規則曲線。實際工作中,變量間未必都有線性關係,曲線擬合是指選擇適當的曲線類型來擬合觀測數據,並用擬合的曲線方程分析兩變量間的關係。所謂曲線擬合方法是由給定的離散數據點,建立數據關係(數學模型),求出一系列微小的直線段把這些插值點連接成曲線,只要插值點的間隔選擇得當,就可以形成一條光滑的曲線。比如獲取的數據很多,或者數據很雜亂,可能很難甚至無法辨認出其中的發展趨勢和模式。所以爲了估算出一條趨勢,從而就用到擬合估算

代碼:

import numpy as np
import matplotlib.pyplot as plt
import csv
import sys
filename = "unemployment-rate-1948-2010.csv"
xa = []
ya = []
try:
    with open(filename) as f:
        reader = csv.reader(f)
        for datarow in reader:
            if reader.line_num != 1:
                ya.append(float(datarow[3]))
                xa.append(int(datarow[1]))
except csv.Error:
    print("Error reading csv file")
    sys.exit(-1)
plt.figure()
plt.scatter(xa[:], ya[:], s=10,c='g',marker='o',alpha=0.5)
poly = np.polyfit(xa, ya, deg = 3)  
plt.plot(xa, np.polyval(poly, xa))  
plt.show()

image-20200411171346827

2、離散型數據處理

散點圖

散點圖,顧名思義就是由一些散亂的點組成的圖表。值由點在圖表中的位置表示。在時間數據中,水平軸表示時間,數值則在垂直軸上。散點圖用位置作爲視覺線索。如果將圖表區域比做一個盤子,那麼這些散圖的點就是“大珠小珠落玉盤”,有如一顆顆繁星,分佈在廣袤的天空。在比較的效果中,散點圖包含的數據越多,效果越好

這類圖形就是散點圖,特點是能直觀表現出影響因素和預測對象之間的總體關係趨勢。優點是能通過直觀醒目的圖形方式反映變量間關係的變化形態,以便決定用何種數學表達方式來模擬變量之間的關係。這裏使用的從此網站(http://datasets.flowingdata.com/flowingdata_subscribers.csv)下載的數據源,關於FlowingData網站於2010年1月計算的訂閱者的數量,最後得出的圖表如圖3-10。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hQvfDcoh-1589507131269)(file:///C:/Users/ASUS/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)]

從圖3-10可以看出,這個散點圖呈現的是上升的趨勢,但是在1月的中旬的時候突然下降很大,這個數據就有可能是數據報告出現錯誤。散點圖不僅可傳遞變量間關係類型的信息,也能反映變量間關係的明確程度。python代碼實現如下:

import pandas as pd
from matplotlib import pyplot as plt
subscriber=pd.read_csv("data/flowingdata_subscribers.csv")
fig,ax=plt.subplots()
time=[pd.to_datetime(i) for i in subscriber["Date"]]
ax.plot(time,subscriber["Subscribers"],"o",color="blue")
ax.set(xlabel="Date",ylabel="Number of subsribers")
ax.set_title("Growth of subscribers --- Jan 2010")
ax.annotate("2 days where \nit went wrong",xy=(0.43,0.06),xycoords='axes fraction',\
            xytext=(0.56,0.1),textcoords='axes fraction',\
            arrowprops=dict(facecolor='black', shrink=0.05))
ax.annotate("25047",xy=(0.046,0.8),xycoords='axes fraction',\
            xytext=(0.004,0.68),textcoords='axes fraction',\
            arrowprops=dict(arrowstyle="-"))
ax.annotate("27611\n(+10%)",xy=(0.955,0.92),xycoords='axes fraction',\
            xytext=(0.905,0.76),textcoords='axes fraction',\
            arrowprops=dict(arrowstyle="-"))
ax.spines["left"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["top"].set_visible(False)
plt.show()

柱形圖

柱形圖又稱條形圖、直方圖,是以寬度相等的條形高度或長度的差異來顯示統計指標數值多少或大小的一種圖形。柱形圖簡明、醒目,是一種常用的統計圖形。圖3-11顯示了其基本框架。

柱形圖一般用於顯示一段時間內的數據變化或顯示各項之間的比較情況。另外,數值的體現就是柱形的高度。柱形越矮數值越小,柱形越高數值越大。還有柱形的寬度與相鄰柱形間的間距決定了整個柱形圖的視覺效果是否美觀。如果柱形的寬度小於間距的話,則會給讀者在讀表的時候注意力集中在空白處而忽略了數據。所以合理的選擇寬度很重要。下面講個簡單的列子說明下怎麼在python中創建柱形圖。數據來源(http://datasets.flowingdata.com/ hot-dog-contest-winners.csv),過去30年的熱狗大胃王的比賽結果。最終圖表如圖3-12所示。

image-20200411234953329

                            圖3-12  大胃王比賽成績的柱形圖

從圖表所示,獲勝者從最初的10個左右到後面60左右,可以看出差不多是增長的趨勢。具體的python程序如下。

from pyecharts import Bar, Scatter3D
from pyecharts import Page
import csv
page = Page()

bar = Bar("柱狀圖數據堆疊示例")
filename = "data/hot-dog-contest-winners.csv"
datax = []
datay = []
with open(filename) as f:
    reader = csv.reader(f)
    for datarow in reader:
        if reader.line_num != 1:
            datay.append(datarow[2])
            datax.append(datarow[0])
bar.add("A", datax, datay, is_stack=True)
page.add(bar)
page.render()

堆疊柱形圖

堆疊柱形圖的幾何形狀和常規柱形圖很相似,在柱形圖中,數據值爲並行排列,而在堆疊柱圖則是一個個疊加起來的。它的特點就是如果數據存在子分類,並且這些子分類相加有意義的話,此時就可以使用堆疊柱形圖來表示。

堆疊柱形圖也是一個使用頻繁的一個圖標類型,這裏使用python實現。也是先載入源數據,(http://datasets.flowingdata.com/hot-dog-places.csv)下載數據然後畫圖。圖表如圖3-14所示。

image-20200411235005295

                         圖3-14  熱狗大胃王的堆疊柱形圖

源數據是一個熱狗大胃王比賽,這裏沒有隻關注冠軍的數據,而是關注了前三名的選手數據。所以每一個柱形就包含三個子柱形,每個子柱形就表示前三名的其中一名選手的數據。python的實現代碼如下,這裏是將源數據事先下載到本地目錄,直接讀取的,也可以直接通過url獲取,這裏就不概述了。

from pyecharts import Bar, Scatter3D
from pyecharts import Page
import csv
page = Page()
bar = Bar("柱狀圖數據堆疊示例")
filename = "data/hot-dog-places.csv"
datax = []
datay = []
with open(filename) as f:
     reader = csv.reader(f)
     for datarow in reader:
         datax.append(datarow)
x= datax[0]
y1=datax[1]
y2=datax[2]
y3=datax[3]
bar.add("A", x, y1, is_stack=True)
bar.add("B", x, y2, is_stack=True)
bar.add("c", x, y2, is_stack=True)
page.add(bar)
page.render()

八、比例數據可視化

比例數據介紹

對於比例,我們通常想要得到最大值、最小值和總體分佈。前兩者比較簡單,將數據由小到大進行排列,位於兩端的分別就是最小值和最大值。對於投票選舉結果的處理,那麼它們就分別代表了得票最少的被選舉人和得票最多的被選舉人。如果你繪製了食物各部分的卡路里含量圖,那麼就會看到哪部分的卡路里最少,哪部分的卡路里含量最多。

其實,對於最小值和最大值我們沒有必要用圖表來展現。我們真正所感興趣的應該是比例的分配。投票選舉中某個被選舉人與其他被選舉人有什麼不同?脂肪、蛋白質、碳水化合物都含有同樣的卡路里嗎?是不是存在某一種卡路里含量佔絕大多數?

餅圖

餅圖採用了餅乾的隱喻,用環狀方式呈現各分量在整體中的比例。這種分塊方式是環狀樹圖等可視化表達的基礎。餅圖是非常常見的,常用於統計學模型。

餅圖的原理也是很簡單的。如圖4-1所示,首先一個圓代表了整體,然後把它們切成楔形,每一個楔形都代表整體中的一部分。所有楔形所佔百分比的總和應該等於100%,如果不等,那就表明出錯了。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YVsYLa8D-1589507131282)(file:///C:/Users/ASUS/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]

​ 圖4-1 餅圖的基本框架

有些人可能不太喜歡使用餅圖,因爲它不太擅於對數據精確的表示,所以他們認爲餅圖對數據可視化並沒有很好的效果。確實,餅圖沒有體現精確的數據,但是餅圖可以呈現各部分在整體中的比列,能夠體現部分與整體之間的關係。那如果我們抓住餅圖的這一優點,良好的組織數據,餅圖對於數據的可視化還是有幫助的。

創建餅圖:

代碼:

from pyecharts import Pie
import pandas as pd
vote_result = pd.read_csv('data/vote_result.csv')
pie = Pie("數據可視化-用戶感興趣領域",
          "以下是讀者的投票結果。\n"
          "讀者對金融、醫療保健、市場業3個領域最感興趣。",title_pos='left')
#pie = Pie("餅圖示例")
pie.add("", vote_result['Areas_of_interest'], vote_result['Votes'], center=[60, 60],legend_orient="vertical",
    legend_pos="right",is_label_show=True)
#pie.add("", vote_result['Areas_of_interest'], vote_result['Votes'],is_legend_show=False,is_label_show=True)
#pie.add("", vote_result['Areas_of_interest'], vote_result['Votes'], is_label_show=False)
pie.render('餅圖.html')

截圖

image-20200412113554468

環形圖

代碼:

from pyecharts import Pie
import pandas as pd

vote_result = pd.read_csv('data/vote_result.csv')
pie = Pie("數據可視化-用戶感興趣領域",
          "以下是讀者的投票結果。\n"
          "讀者對金融、醫療保健、市場業3個領域最感興趣。",title_pos='left')
pie.add("", vote_result['Areas_of_interest'], vote_result['Votes'], center=[60, 60],legend_orient="vertical",
radius=[30, 75],legend_pos="right",is_label_show=True)
pie.render('2.環形圖.html')

截圖:

image-20200412114626708

堆疊柱形圖

代碼:

from pyecharts import Bar
import pandas as pd
pre_approval_rate = pd.read_csv('data/presidential_approval_rate.csv')
bar = Bar("柱狀圖數據堆疊示例")
bar.add("支持", pre_approval_rate['political_issue'], pre_approval_rate['support'], is_stack=True)
bar.add("反對", pre_approval_rate['political_issue'], pre_approval_rate['oppose'], is_stack=True)
bar.add("不發表意見", pre_approval_rate['political_issue'], pre_approval_rate['no_opinion'],xaxis_rotate=30, is_stack=True)
bar.render('3.堆疊柱形圖.html')


#另外一種寫法
from pyecharts import Bar
import pandas as pd
pre_approval_rate = pd.read_csv('data/presidential_approval_rate.csv')
bar = Bar("柱狀圖數據堆疊示例",title_pos='center')
list_support = ['支持','反對','不發表意見']
for i in range(pre_approval_rate.iloc[:,0].size):
    issue = pre_approval_rate.loc[i,'political_issue']
    bar.add(issue, list_support, pre_approval_rate.loc[i,['support','oppose','no_opinion']], legend_orient="vertical",legend_pos="right",is_stack=True)
bar.render('3.2堆疊柱形圖.html')

截圖:

image-20200412114916503

樹圖

代碼

import os
import json
import codecs
from pyecharts import Tree
with codecs.open(os.path.join("data", "GDP_data.json"), "r", encoding="utf-8") as f:
    j = json.load(f)
data = [j]
tree = Tree(width=1200, height=800)
tree.add("", data) #, tree_collapse_interval=2
tree.render('4.樹圖.html')

image-20200412115854439

矩形樹圖

# encoding:utf-8
import os
import json
from pyecharts import TreeMap
with open(os.path.join("data/GDP_data_1.json"),"r", encoding="utf-8") as f:
    data = json.load(f)
treemap = TreeMap("矩形樹圖示例", width= 1200, height=600)
treemap.add("演示數據", data, is_labelshow= True, label_pos='inside')
#,treemap_left depth=1
treemap.render('矩形樹圖.html')

image-20200415165659303

九、文本數據可視化

1.文本數據在大數據中的應用

鑑於人們對文本信息需求的多樣性,我需要從不同層級提取與呈現文本信息。一般把對文本的理解需求分成三級:詞彙級(Lexical Level)、
語法級(Syntactic Level)和語義級(Semantic Level)。不同級的信息挖掘方法也不同,詞彙級是使用各類分詞算法,而語法級使用句法
分析算法,語義級則是使用主題抽取算法。文本信息的類別多種多樣,一般包括單文本、文檔集合和時序文本數據三大類。針對文本信息的多樣性,人們不僅提出多種普適性的可視化技術,並針對特定的分析需求研發了具有特性的可視化技術。

image-20200426083323028

2.文本信息分析

文本屬於非結構化數據,不能直接用於可視化,需要使用向量符號將文本度量成數學模型。常用的將文本轉化爲向量的方法:
1、VSM(向量空間模型,vector space model)
2、主題抽取,如LDA( Latent Dirichlet Allocation,文檔主題生成
模型 )、LSI(Latent Semantic Indexing,隱含語義檢索模型)

2.1 VSM

向量空間模型是使用向量符號對文本進行度量的代數模型,把對文本內容的處理簡化爲向量空間中的向量運算,並且以空間相似度表達
語義相似度。
VSM的兩大核心:
1、詞袋模型
2、TF-idf度量

2.1.1 詞袋模型

詞袋模型(Bag of Words)指在信息檢索中,將某一文本僅看作是一個詞集合,而不考慮其語法、詞序等信息。文本中每個詞相互獨立,不依賴於
其他詞的出現與否。詞袋模型是向量空間模型構造文本向量的常用方法之一,常用來提取詞彙級文本信息。
詞袋模型,就是忽略掉詞序、語法和語句,過濾掉對文本內容影響較弱的詞(停用詞),將文本看作一系列關鍵詞彙的集合所形成的向量,每個詞
匯表示一個維度,維度的值就是該詞彙在文檔中出現的頻率。

以Charles Dickens的《雙城記》中的一段文字爲例。
“It was the best of times, it was the worst of times, it was the age of wisdom,
it was the age of foolishness.”
根據詞袋模型的概念,可以構建一個詞袋,假設建立一個數組用於映射匹配:
[it、was、the、best、of、times、worst、age、wisdom、foolishness]
則上述四個句子可以用以下向量表示:
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0]、 [1, 1, 1, 0, 1, 1, 1, 0, 0, 0]、 [1, 1, 1, 0, 1, 0, 0, 1, 1, 0]、
[1, 1, 1, 0, 1, 0, 0, 1, 0, 1]
這四個詞頻向量就是詞袋模型,可以很明顯的看到語序關係已經完全丟失。

2.1.2 TF-IDF

TF-IDF(Term Frequency-Inverse Document Frequency)是一種用於信息檢索與數據挖掘的常用加權技術。
TF的含義是詞頻(Term Frequency),是一個詞語在一篇文件中出現的次數除以該文件的總詞語數。
IDF的含義是逆文本頻率指數(Inverse Document Frequency)。即文本頻率(DF)的倒數。DF指包含的某個詞的文件個數除以該文檔集裏文件總數。

TF-IDF用於評估某個單詞或字在一個文檔集或語料庫的重要程度。
TF-IDF的主要思想是:如果某個詞或短語在一篇文章中出現的頻率(TF)高,並且在其他文章中很少出現,則可認爲此詞或者短語具有很好的類別區
分能力,適合用來分類。也就是說,字詞在某個文檔的重要性與它在這個文檔中出現的次數正相關,但同時也會隨着它在文檔集合中出現的頻率增加而下降。

image-20200426085050826

image-20200426085113389

2.2 主題抽取

一個文檔的語義內容可描述爲多主題的組合表達,一個主題可認爲是一系列字詞的概率分佈。
主題模型是對文字中隱含主題的一種建模方法,它從語義級別描述文檔集中的各個文本信息。
文本主題的抽取算法大致可分爲兩類:基於貝葉斯的概率模型和基於矩陣分解的非概率模型。

1、概率模型:其主題被當成多個詞項的概率分佈,文檔可以理解成由多個主題的組合而產生的。如LDA文本主題生成模型,是一個三層貝葉斯概率模
型,包含詞、主題和文檔三層結構。我們認爲一篇文章的每個詞都是通過“以一定概率選擇了某個主題,並從這個主題中以一定概率選擇某個詞語”這樣一個過程得到。文檔到主題、主題到詞服都從多項式分佈。
2、非概率模型:它將詞項-文檔矩陣投影到K維空間中,每個維度代表一個主題。在主題空間中,每個文檔由K個主題的線性組合來表示。如LSI ,是
基於主題間的正交性假設,採用SVD分解詞項-文檔矩陣的非概率模型。

3.文本信息可視化

文本數據可視化可以分爲文本內容的可視化、文本關係的可視化以及文本多特徵信息的可視化。
• 文本內容可視化是對文本內的關鍵信息分析後的展示;
• 文本關係的可視化既可以對單個文本進行內部的關係展示,也可以對多個文本進行文本之間的關係展示;
• 文本多特徵信息的可視化,是結合文本的多個特徵進行全方位的可視化展示。

3.1 文本內容可視化

文本的內容可以通過關鍵詞、短語、句子和主題進行展現。
對於文本內容的可視化,主要體現在以下三方面:
• 關鍵詞可視化
• 時序文本可視化
• 文本分佈可視化

3.1.1 關鍵詞可視化

一個詞語若在一個文本中出現的頻率較高,那麼,這個詞語就可能是這個文本的關鍵詞,它可以在一定程度上反映出一個文本內容所要表
達的含義。
關鍵詞可視化是用一個文本中的關鍵詞來展示該文本的內容。常用
技術有:
• 標籤雲(tag cloud)
• 文檔散( DocuBurst )

關鍵詞可視化——標籤雲

標籤雲(Tag Clould)是一種最常見的、簡單的關鍵詞可視化方法,主要可分爲如下兩步。
① 統計文本中詞語的出現頻率,提取出現頻率較高的關鍵詞。
② 按照一定的順序和規律將這些關鍵詞展示出來。例如,用顏色的深淺,或者字體的大小,來區分關鍵詞的重要性。

關鍵詞可視化——文檔散
文檔散(DocuBurst)是由多倫多大學的Christopher Collins教授製作的一個在線文本分析可視化工具,通過導入TXT格式的文本數據,
生成HTML格式的可視化圖片。文檔散使用詞彙庫中的結構關係來佈局關鍵詞,同時使用詞語關係網中具有上下語義關係的詞語來佈局關鍵詞,從而揭示文本中的內容。上下語義關係是指詞語之間往往存在語義層級的關係,也就是說,一些詞語是某些詞語的下義詞。而在一篇文章中,具有上下語義關係的詞語一般是同時存在的。

image-20200426090742987

3.1.2 時序文本可視化

時序文本的特性就是具有時間性和順序性,比如,新聞會隨着時間
變化,小說的故事情節會隨着時間變化。
時序文本可視化常用技術有:
• 主題河流(ThemeRiver)
• 文本流(TextFlow)
• 故事流(StoryFlow)

主題河流(ThemeRiver)是由Susan Havre等學者於2000年提出的一種時序數據可視化方法,主要用於反映文本主題強弱變化的過程。
經典的主題河流模型包括以下兩個屬性。
① 顏色,表示主題的類型,一個主題用一個單一顏色的涌流表示。但是,顏色種類有限,若使用一種顏色表示一個主題,則會限制主題的數量,因此,可以使用一種顏色表示一類主題。
② 寬度,表示主題的數量(或強度),涌流的狀態隨着主題的變化,可能擴展、收縮或者保持不變。

image-20200426090852890

image-20200426090909957

image-20200426090929207

3.1.3 文本分佈可視化

前面的文檔數據可視化方法都是通過關鍵詞、文本主題來總結文本內容,但是文檔中的其他特徵,如詞語的分佈情況、句子的平均長度、
詞彙量等並沒有展示出來。
體現文本分佈的可視化方法有:
• 文本弧(TextArc)
• 文獻指紋(Literature Fingerprinting)

文本分佈可視化——文本弧
文本弧(TextArc)可視化技術不僅可以展示詞頻,還可以展示詞的分佈情況。文本弧的特性如下:
① 用一條螺旋線表示一篇文章,螺旋線的首尾對應着文章的首尾,文章的詞語有序地佈局在螺旋線上。
② 若詞語在整片文章中出現都比較頻繁,則靠近畫布的中心分佈。
③ 若詞語只是局部出現得比較頻繁,則靠近螺旋線分佈。
④ 字體的大小和顏色深度代表着詞語的出現頻率

image-20200426091033087

文本分佈可視化——文獻指紋
文獻指紋(Literature Fingerprinting)是體現全文特徵分佈的一項工作。一個像素塊代表一段文本,一組像素塊代表一本書。顏色映射的是文本特徵,如使用句子的平均長度進行顏色映射。

image-20200426091101932

3.2 文本關係可視化

文本關係包括文本內或者文本間的關係,以及文本集合之間的關係,比如文本的相似性、互相引用的情況、鏈接等。文本關係可
視化的目的就是呈現出這些關係。
• 文本內的關係有詞語的前後關係;
• 文本間的關係有網頁之間的超鏈接關係,文本之間內容的相似性,文本之間的引用等;
• 文本集合之間的關係是指文本集合內容的層次性等關係。

3.2.1 文本內容關係可視化

文本內容關係可視化經常採用的是基於圖的方式進行可視化,如詞語樹(word tree)、網絡短語(phrase nets)、矩陣樹圖(NewsMap)等。

文本內容關係可視化——word tree
詞語樹(Word Tree)使用樹形圖展示詞語在文本中的出現情況,可以直觀地呈現出一個詞語和其前後的詞語。用戶可自定義感興趣的詞語作爲中心節點。中心節點向前擴展,就是文本中處於該詞語前面的詞語;中心節點向後擴展,就是文本中處於該詞語後面的詞語。字號大小代表了詞語在文本中出現的頻率。

image-20200426094054394

文本內容關係可視化——phrase nets短語網絡(Phrase Nets)包括以下兩種屬性。
① 節點,代表一個詞語或短語。
② 帶箭頭的連線,表示節點與節點之間的關係,這個關係需要用戶定義,比如,“A is B”,其中的is用連線表示,A和B是is前
後的兩個節點詞語。A在is前面,B在is後面,那麼,箭頭就由A指向B。連線的寬度越寬,就說明這個短語在文中出現的頻率越高

image-20200426094142866

image-20200426094209618

3.2.2 文檔間關係可視化
當對多個文檔進行可視化展示時,針對文本內容做可視化的方法就不適合了。此時可以引入向量空間模型來計算出各個文檔之間的相似性,
單個文檔被定義成單個特徵向量,最終以投影等方式來呈現各文檔之間的關係。
文檔間關係可視化的方法有:星系視圖、文檔集抽樣投影、主題地貌(Theme map)等

文檔間關係可視化——星系視圖
星系視圖(Galaxy View)可用於表徵多個文檔之間的相似性。假設一篇文檔是一顆星星,每篇文檔都有其主題,將所有文檔按照主題投影到二維平面上,就如同星星在星系中一樣。文檔的主題越相似,星星之間的距離就越近;文檔的主題相差越大,星星之間的距離就越遠。星星聚集得越多,就表示這些文檔的主題越相近,並且數量較多;若存在多個聚集點則說明文檔集合中包含多種主題的文檔。

image-20200426094319405

文檔間關係可視化——文檔集抽樣投影
當一個文檔集中包含的文檔數量過大時,投影出來的星系視圖中就會產生很多重疊的星星。爲了避免這種重疊情況的出現,用戶可以對文檔集進行抽樣,有選擇性地抽取部分文檔進行投影,這樣可以更加清晰地顯示每個樣本。

文檔間關係可視化——主題地貌
主題地貌(ThemeScape)是對星系圖的改進。把等高線加入投影的二維平面中,文檔相似性相同的放在一個等高線內,再用顏
色來編碼文本分佈的密集程度,把二維平面背景變成一幅地圖,這樣就把剛纔星系圖中的星團變成了一座座山丘。文檔越相似,則分佈約密集,這座山峯就越高。

image-20200509112441930

3.3 文本多特徵信息可視化——平行標籤雲

平行標籤雲(Parallel Tag Clouds)結合了平行座標(該視圖在多維數據可視化中經常使用)和標籤雲視圖。每一列是一個層面的標籤雲,然後連接的折線展現了選中標籤在多個層面的分佈。實質是將標籤雲在水平方向上基於多個不同的特徵進行顯示,每一個特徵對應着一列標籤雲,列與列之間的特徵都不一樣。

文本多特徵信息可視化——FaceAtlas
FaceAtlas 結合了氣泡集和節點-鏈接圖兩種視圖,用於表達文本各層面信息內部和外部的關聯。每個節點表示一個實體,用 KDE 方法刻畫出氣泡圖的輪廓,然後用線將同一層面的實體鏈接起來,一種顏色代表一種實體。

image-20200426094501934

image-20200426094830147

4.jieba分詞

jieba.cut 方法接受三個輸入參數: 需要分詞的字符串;cut_all 參數用來控制是否採用全模式;HMM 參數用來控制是否使用 HMM 模型
# encoding=utf-8
import jieba

seg_list = jieba.cut("我來到北京清華大學", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式
# Full Mode: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學

seg_list = jieba.cut("我來到北京清華大學", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精確模式
# Default Mode: 我/ 來到/ 北京/ 清華大學

image-20200427085305879

停用詞:

import jieba
content = 'I have a dream that one day \
this nation will rise up and live out the \
true meaning of its creed: "We hold these \
truths to be self-evident, that all men are created equal."'
seg_list = jieba.cut(content)
stopwords = ['a','the','that',' ','"',':','of','to','-',',','be','.','this','will','its','these','are','was','\n']
final=[]
for seg in seg_list:
    if seg not in stopwords:
        final.append(seg)
print(len(final),",".join(final))

import jieba
text ='''
"It was the best of times,
it was the worst of times,
it was the age of wisdom,
it was the age of foolishness."
'''
seg_list = jieba.cut(text.lower())
stopwords = ['a','the','that',' ','"',':','of',
             'to','-',',','be','.','this','will',
             'its','these','are','was','\n']
final=[]
for seg in seg_list:
    if seg not in stopwords:
        final.append(seg)
print(len(final),",".join(final))
word_dict = {}
for word in final:
    if word in word_dict:  # word已經出現過,將計數增加1
        word_dict[word] += 1
    else:  # word還沒有出現過,創建新的鍵值對
        word_dict[word] = 1
print(word_dict)

image-20200427090008077

基於TF-IDF算法進行關鍵詞抽取
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

sentence 爲待提取的文本

topK 爲返回幾個 TF/IDF 權重最大的關鍵詞,默認值爲 20

withWeight 爲是否一併返回關鍵詞權重值,默認值爲 False

allowPOS 僅包括指定詞性的詞,默認值爲空,即不篩選
from jieba import analyse
# 引入TF-IDF關鍵詞抽取接口
tfidf = analyse.extract_tags

# 原始文本
text = "線程是程序執行時的最小單位,它是進程的一個執行流,\
        是CPU調度和分派的基本單位,一個進程可以由很多個線程組成,\
        線程間共享進程的所有資源,每個線程有自己的堆棧和局部變量。\
        線程由CPU獨立調度執行,在多CPU環境下就允許多個線程同時運行。\
        同樣多線程也可以實現併發操作,每個請求分配一個線程來處理。"

# 基於TF-IDF算法進行關鍵詞抽取
keywords = tfidf(text)
print("keywords by tfidf:") 
# 輸出抽取出的關鍵詞
for keyword in keywords:
    print(keyword ,end="/")

image-20200427091801856

5.wordcloud詞雲圖

#coding=utf-8
import wordcloud
import matplotlib.pyplot as plt
w = wordcloud.WordCloud()
w.generate("President Xi Jinping and Premier \
           Li Keqiang sent condolence messages \
           on Sunday to their Sri Lankan \
           counterparts after multiple \
           deadly attacks shook the country.")
w.to_file(r'G:\pythonProject\pc\數據可視化\文本數據\results\result.png')
# 以下代碼顯示圖片
plt.imshow(w)
plt.axis("off")
plt.show()

image-20200427094530621

import wordcloud
import matplotlib.pyplot as plt
w = wordcloud.WordCloud(font_path='simkai.ttf')
w.generate("使用 直方圖 和 密度曲線 展現 世界 各國 的 出生率")
w.to_file(r'G:\pythonProject\pc\數據可視化\文本數據\results\result2.png')
# 以下代碼顯示圖片
plt.imshow(w)
plt.axis("off")
plt.show()

image-20200427094719220

#Wordcloud自定義字體以支持中文,同時引入jieba中文分詞
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator, STOPWORDS
import jieba

# 讀入背景圖片
backgroud_Image = plt.imread(r'G:\pythonProject\pc\數據可視化\文本數據\data\love.jpg')
# 讀取要生成詞雲的文件
text_from_file_with_apath = open("data/test.txt",encoding='utf-8').read()
# 通過jieba分詞進行分詞並通過空格分隔
wordlist_after_jieba = jieba.cut(text_from_file_with_apath, cut_all=False)
wl_space_split = " ".join(wordlist_after_jieba)
my_wordcloud = WordCloud(
    background_color='white',    # 設置背景顏色
    mask=backgroud_Image,        # 設置背景圖片
    max_words=100,               # 設置最大顯示的字數
    stopwords=STOPWORDS,         # 設置停用詞
    ###########################################添加下面這行代碼,同時百度,下載字體庫到目錄中
    font_path='simkai.ttf',# 設置字體格式,如不設置顯示不了中文
#     max_font_size=40,            # 設置字體最大值
    random_state=300,     # 設置有多少種隨機生成狀態,即有多少種配色方案
    scale=5,              #按照比例進行放大畫布
    width=1600,
    height=800
    ).generate(wl_space_split)

# 根據圖片生成詞雲顏色
image_colors = ImageColorGenerator(backgroud_Image)
my_wordcloud.recolor(color_func=image_colors)
my_wordcloud.to_file('result.png')
# 以下代碼顯示圖片
plt.imshow(my_wordcloud)
plt.axis("off")
plt.show()

image-20200427110025860

實驗

1、詞雲圖

add(name, attr, value,
    shape="circle",
    word_gap=20,
    word_size_range=None,
    rotate_step=45)
name -> str
圖例名稱
attr -> list
屬性名稱
value -> list
屬性所對應的值
shape -> list
詞雲圖輪廓,有'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star'可選
word_gap -> int
單詞間隔,默認爲 20。
word_size_range -> list
單詞字體大小範圍,默認爲 [12, 60]。
rotate_step -> int
旋轉單詞角度,默認爲 45

代碼:

from pyecharts import WordCloud
name = [
    'Sam S Club', 'Macys', 'Amy Schumer', 'Jurassic World', 'Charter Communications',
    'Chick Fil A', 'Planet Fitness', 'Pitch Perfect', 'Express', 'Home', 'Johnny Depp',
    'Lena Dunham', 'Lewis Hamilton', 'KXAN', 'Mary Ellen Mark', 'Farrah Abraham',
    'Rita Ora', 'Serena Williams', 'NCAA baseball tournament', 'Point Break']
value = [
    10000, 6181, 4386, 4055, 2467, 2244, 1898, 1484, 1112,
    965, 847, 582, 555, 550, 462, 366, 360, 282, 273, 265]

wordcloud = WordCloud(width=1300, height=620)
wordcloud.add("", name, value, word_size_range=[20, 100])
wordcloud.render(path="1.2詞雲圖.html")

image-20200412160950726

第二種用pandas,主要提取兩列數據

image-20200412161326881

from pyecharts import WordCloud
import pandas as pd
post_data = pd.read_csv('data/post_data.csv')
wordcloud = WordCloud(width=1300, height=620)
post_data2=post_data.groupby(by=['category']).agg({'views':sum}).reset_index()
wordcloud.add("", post_data2['category'], post_data2['views'], word_size_range=[20, 100])
wordcloud.render(path="1.詞雲圖.html")

image-20200412161237689

2、主題河流

代碼

from pyecharts import ThemeRiver

data = [
    ['2015/11/08', 10, '分支1'], ['2015/11/09', 15, '分支1'], ['2015/11/10', 35, '分支1'],
    ['2015/11/14', 7, '分支1'], ['2015/11/15', 2, '分支1'], ['2015/11/16', 17, '分支1'],
    ['2015/11/17', 33, '分支1'], ['2015/11/18', 40, '分支1'], ['2015/11/19', 32, '分支1'],
    ['2015/11/20', 26, '分支1'], ['2015/11/21', 35, '分支1'], ['2015/11/22', 40, '分支1'],
    ['2015/11/23', 32, '分支1'], ['2015/11/24', 26, '分支1'], ['2015/11/25', 22, '分支1'],
    ['2015/11/08', 35, '分支2'], ['2015/11/09', 36, '分支2'], ['2015/11/10', 37, '分支2'],
    ['2015/11/11', 22, '分支2'], ['2015/11/12', 24, '分支2'], ['2015/11/13', 26, '分支2'],
    ['2015/11/14', 34, '分支2'], ['2015/11/15', 21, '分支2'], ['2015/11/16', 18, '分支2'],
    ['2015/11/17', 45, '分支2'], ['2015/11/18', 32, '分支2'], ['2015/11/19', 35, '分支2'],
    ['2015/11/20', 30, '分支2'], ['2015/11/21', 28, '分支2'], ['2015/11/22', 27, '分支2'],
    ['2015/11/23', 26, '分支2'], ['2015/11/24', 15, '分支2'], ['2015/11/25', 30, '分支2'],
    ['2015/11/26', 35, '分支2'], ['2015/11/27', 42, '分支2'], ['2015/11/28', 42, '分支2'],
    ['2015/11/08', 21, '分支3'], ['2015/11/09', 25, '分支3'], ['2015/11/10', 27, '分支3'],
    ['2015/11/11', 23, '分支3'], ['2015/11/12', 24, '分支3'], ['2015/11/13', 21, '分支3'],
    ['2015/11/14', 35, '分支3'], ['2015/11/15', 39, '分支3'], ['2015/11/16', 40, '分支3'],
    ['2015/11/17', 36, '分支3'], ['2015/11/18', 33, '分支3'], ['2015/11/19', 43, '分支3'],
    ['2015/11/20', 40, '分支3'], ['2015/11/21', 34, '分支3'], ['2015/11/22', 28, '分支3'],
    ['2015/11/14', 7, '分支4'], ['2015/11/15', 2, '分支4'], ['2015/11/16', 17, '分支4'],
    ['2015/11/17', 33, '分支4'], ['2015/11/18', 40, '分支4'], ['2015/11/19', 32, '分支4'],
    ['2015/11/20', 26, '分支4'], ['2015/11/21', 35, '分支4'], ['2015/11/22', 40, '分支4'],
    ['2015/11/23', 32, '分支4'], ['2015/11/24', 26, '分支4'], ['2015/11/25', 22, '分支4'],
    ['2015/11/26', 16, '分支4'], ['2015/11/27', 22, '分支4'], ['2015/11/28', 10, '分支4'],
    ['2015/11/08', 10, '分支5'], ['2015/11/09', 15, '分支5'], ['2015/11/10', 35, '分支5'],
    ['2015/11/11', 38, '分支5'], ['2015/11/12', 22, '分支5'], ['2015/11/13', 16, '分支5'],
    ['2015/11/14', 7, '分支5'], ['2015/11/15', 2, '分支5'], ['2015/11/16', 17, '分支5'],
    ['2015/11/17', 33, '分支5'], ['2015/11/18', 40, '分支5'], ['2015/11/19', 32, '分支5'],
    ['2015/11/20', 26, '分支5'], ['2015/11/21', 35, '分支5'], ['2015/11/22', 4, '分支5'],
    ['2015/11/23', 32, '分支5'], ['2015/11/24', 26, '分支5'], ['2015/11/25', 22, '分支5'],
    ['2015/11/26', 16, '分支5'], ['2015/11/27', 22, '分支5'], ['2015/11/28', 10, '分支5'],
    ['2015/11/08', 10, '分支6'], ['2015/11/09', 15, '分支6'], ['2015/11/10', 35, '分支6'],
    ['2015/11/11', 38, '分支6'], ['2015/11/12', 22, '分支6'], ['2015/11/13', 16, '分支6'],
    ['2015/11/14', 7, '分支6'], ['2015/11/15', 2, '分支6'], ['2015/11/16', 17, '分支6'],
    ['2015/11/17', 33, '分支6'], ['2015/11/18', 4, '分支6'], ['2015/11/19', 32, '分支6'],
    ['2015/11/20', 26, '分支6'], ['2015/11/21', 35, '分支6'], ['2015/11/22', 40, '分支6'],
    ['2015/11/23', 32, '分支6'], ['2015/11/24', 26, '分支6'], ['2015/11/25', 22, '分支6']
]
colors_list=['#FFA07A','#32CD32','#4169E1','#FAA460','#F0E68C','#8c564b','#e377c2','#7f7f7f','#bcbd22','#17becf']#備用顏色列表
tr = ThemeRiver("主題河流圖示例圖")
tr.add(['分支1', '分支2', '分支3', '分支4', '分支5', '分支6'], data, is_label_show=False,label_color=colors_list)
tr.render(path="2.主題河流.html")

image-20200412161451940

3、關係圖

from pyecharts import Graph

nodes = [{"name": "結點1", "symbolSize": 10},
         {"name": "結點2", "symbolSize": 20},
         {"name": "結點3", "symbolSize": 30},
         {"name": "結點4", "symbolSize": 40},
         {"name": "結點5", "symbolSize": 50},
         {"name": "結點6", "symbolSize": 40},
         {"name": "結點7", "symbolSize": 30},
         {"name": "結點8", "symbolSize": 20}]
links = []
for i in nodes:
    for j in nodes:
        links.append({"source": i.get('name'), \
                      "target": j.get('name')})
graph = Graph("關係圖-力引導佈局示例")
graph.add("", nodes, links, repulsion=8)
graph.render()
graph

image-20200427093047055

graph = Graph("關係圖-環形佈局示例")
graph.add(
    "",
    nodes,
    links,
    is_label_show=True,
    graph_repulsion=8000,
    graph_layout="circular",
    label_text_color=None,
)
# graph.render()
# graph

image-20200427093125526

微博轉發關係圖

from pyecharts import Graph
import os
import json
with open(os.path.join("data", "weibo-2.json"), "r", encoding="utf-8") as f:
    j = json.load(f)
    #print(j)
    nodes, links, categories, cont, mid, userl = j
    #這種寫法可以參考
    #print(mid)
graph = Graph("微博轉發關係圖", width=1200, height=600)
graph.add(
    "",
    nodes,
    links,
    categories,
    label_pos="right",
    graph_repulsion=50,
    is_legend_show=False,
    line_curve=0.2,
    label_text_color=None,
)
graph.render(path="3.關係圖.html")

image-20200412162953933

十、多元變量及數據分佈可視化

1、多元變量及數據分佈常用圖形

  • 少數變量

    • 相關性——因果性,相似但不一定相同
  • 多元變量

    • 多個變量直接存在正相關行、負相關行和弱相關性
    • 正相關:線條呈現平行
    • 負相關:線條一直交叉(頂端與底端相連)
    • 弱相關:方向不清晰
  • 數據分佈

    • 通過不同的圖表(例如:散點圖、柱狀圖)來觀察數據分佈
    • 箱線圖
      img
      • 上四分位數於下四分位數之間的範圍稱爲四分位間距
      • 上/下邊界

        [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QlvnGStO-1589507131331)(https://g.yuque.com/gr/latex?%E4%B8%8A%2F%E4%B8%8B%E8%BE%B9%E7%95%8C%20%3D%20%7B%E4%B8%8A%2F%E4%B8%8B%E5%9B%9B%E5%88%86%E4%BD%8D%E6%95%B0%7D%5Cpm1%5Cfrac%7B1%7D%7B2%7D%7B%E5%9B%9B%E5%88%86%E4%BD%8D%E9%97%B4%E8%B7%9D%7D%0A)]

2、數據可視化交互

2018年北京AQI全年走勢圖

代碼:

import pandas as pd
from pyecharts import Line

df = pd.read_csv('data/beijing_AQI_2018.csv')
attr = df['Date']
v1 = df['AQI']
line = Line("2018年北京AQI全年走勢圖", title_pos='center', title_top='18', width=800, height=400)
line.add("AQI值:", attr, v1, mark_line=['average'], is_fill=True, area_color="#000", area_opacity=0.3, mark_point=["max", "min"], mark_point_symbol="circle", mark_point_symbolsize=25)
line.render("2018年北京AQI全年走勢圖.html")

image-20200412171224112

2018年北京PM2.5基本走勢圖

代碼:

import pandas as pd
from pyecharts import Line

df = pd.read_csv('data/beijing_AQI_2018.csv')
attr = df['Date']
v1 = df['PM']
line = Line("2018年北京PM2.5全年走勢圖", title_pos='center', title_top='18', width=800, height=400)
line.add("PM2.5值:", attr, v1, mark_line=['average'], is_fill=True, area_color="#000", area_opacity=0.3, mark_point=["max", "min"], mark_point_symbol="circle", mark_point_symbolsize=25)
line.render("2018年北京PM2.5全年走勢圖.html")

image-20200412171524711

2018年北京月均AQI走勢圖

import numpy as np
import pandas as pd
from pyecharts import Line

df = pd.read_csv('data/beijing_AQI_2018.csv')
dom = df[['Date', 'AQI']]
list1 = []
for j in dom['Date']:
    time = j.split('/')[1]
    list1.append(time)
df['month'] = list1

month_message = df.groupby(['month'])
month_com = month_message['AQI'].agg(['mean'])
month_com.reset_index(inplace=True)
month_com_last = month_com.sort_index()

attr = ["{}".format(str(i) + '月') for i in range(1, 13)]
v1 = np.array(month_com_last['mean'])
v1 = ["{}".format(int(i)) for i in v1]

line = Line("2018年北京月均AQI走勢圖", title_pos='center', title_top='18', width=800, height=400)
line.add("AQI月均值", attr, v1, mark_point=["max", "min"])
line.render("2018年北京月均AQI走勢圖.html")

image-20200412172605181

2018年北京月均PM2.5走勢圖

import numpy as np
import pandas as pd
from pyecharts import Line

df = pd.read_csv('data/beijing_AQI_2018.csv')

dom = df[['Date', 'PM']]
list1 = []
for j in dom['Date']:
    time = j.split('/')[1]
    list1.append(time)
df['month'] = list1

month_message = df.groupby(['month'])
month_com = month_message['PM'].agg(['mean'])
month_com.reset_index(inplace=True)
month_com_last = month_com.sort_index()

attr = ["{}".format(str(i) + '月') for i in range(1, 13)]
v1 = np.array(month_com_last['mean'])
v1 = ["{}".format(int(i)) for i in v1]

line = Line("2018年北京月均PM2.5走勢圖", title_pos='center', title_top='18', width=800, height=400)
line.add("", attr, v1, mark_point=["max", "min"])
line.render("2018年北京月均PM2.5走勢圖.html")

image-20200412172741618

2018年北京季度AQI箱形圖

import pandas as pd
from pyecharts import Boxplot

df = pd.read_csv('data/beijing_AQI_2018.csv')

dom = df[['Date', 'AQI']]
data = [[], [], [], []]
dom1, dom2, dom3, dom4 = data
for i, j in zip(dom['Date'], dom['AQI']):
    time = i.split('/')[1]
    if time in ['1', '2', '3']:
        dom1.append(j)
    elif time in ['4', '5', '6']:
        dom2.append(j)
    elif time in ['7', '8', '9']:
        dom3.append(j)
    else:
        dom4.append(j)

boxplot = Boxplot("2018年北京季度AQI箱形圖", title_pos='center', title_top='18', width=800, height=400)
x_axis = ['第一季度', '第二季度', '第三季度', '第四季度']
y_axis = [dom1, dom2, dom3, dom4]
_yaxis = boxplot.prepare_data(y_axis)
boxplot.add("", x_axis, _yaxis)
boxplot.render("2018年北京季度AQI箱形圖.html")

image-20200412172936192

2018年北京季度PM2.5箱形圖

import pandas as pd
from pyecharts import Boxplot

df = pd.read_csv('data/beijing_AQI_2018.csv')

dom = df[['Date', 'PM']]
data = [[], [], [], []]
dom1, dom2, dom3, dom4 = data
for i, j in zip(dom['Date'], dom['PM']):
    time = i.split('/')[1]
    if time in ['1', '2', '3']:
        dom1.append(j)
    elif time in ['4', '5', '6']:
        dom2.append(j)
    elif time in ['7', '8', '9']:
        dom3.append(j)
    else:
        dom4.append(j)
boxplot = Boxplot("2018年北京季度PM2.5箱形圖", title_pos='center', title_top='18', width=800, height=400)
x_axis = ['第一季度', '第二季度', '第三季度', '第四季度']
y_axis = [dom1, dom2, dom3, dom4]
_yaxis = boxplot.prepare_data(y_axis)
boxplot.add("", x_axis, _yaxis)
boxplot.render("result/2018年北京季度PM2.5箱形圖.html")

image-20200412193439363

2018年北京全年空氣質量情況

import pandas as pd
from pyecharts import Pie

df = pd.read_csv('data/beijing_AQI_2018.csv')

rank_message = df.groupby(['Quality_grade'])
rank_com = rank_message['Quality_grade'].agg(['count'])
rank_com.reset_index(inplace=True)
rank_com_last = rank_com.sort_values('count', ascending=False)

attr = rank_com_last['Quality_grade']
v1 = rank_com_last['count']

pie = Pie("2018年北京全年空氣質量情況", title_pos='center', title_top=0)
pie.add("", attr, v1, radius=[40, 75], label_text_color=None, is_label_show=True, legend_orient="vertical", legend_pos="left", legend_top="%10")
pie.render('result/2018年北京全年空氣質量情況.html')

image-20200412193604341

2018年北京PM2.5指數日曆圖

import datetime
import random
import numpy as np
import pandas as pd
from pyecharts import HeatMap

df = pd.read_csv('data/beijing_AQI_2018.csv')
#v1 = ["{}".format(int(i)) for i in np.array(df['PM'])]

#begin = datetime.date(2018, 1, 1)
#end = datetime.date(2018, 12, 31)

#data = [[str(begin + datetime.timedelta(days=i)), v1[i]] for i in range((end - begin).days + 1)]
#random.randint(1000, 25000)
#data = [[str(begin + datetime.timedelta(days=i)), random.randint(0, 400)] for i in range((end - begin).days + 1)]
dom = df[['Date', 'PM']]
list1 = []
for i, j in zip(dom['Date'], dom['PM']):
    time_list = i.split('/')
    time = datetime.date(int(time_list[0]),int(time_list[1]),int(time_list[2]))
    PM = int(j)
    list1.append([str(time),str(PM)])

heatmap = HeatMap("2018年北京PM2.5指數日曆圖", title_pos='40%', title_top='10', width=800, height=400)
heatmap.add(
    "",
    list1,
    is_calendar_heatmap=True,
    visual_text_color="#000",
    visual_range_text=["", ""],
    visual_range=[0, 300],
    calendar_cell_size=["auto", 30],
    is_visualmap=True,
    calendar_date_range="2018",
    visual_orient="horizontal",
    visual_pos="26%",
    visual_top="70%",
    is_piecewise=True,
    visual_split_number=6,
)
heatmap.render('result/2018年北京PM2.5指數日曆圖.html')

image-20200412193815976

2018年北上廣深AQI軸向運動圖

import numpy as np
import pandas as pd
from pyecharts import Line

citys = ['beijing', 'shanghai', 'guangzhou', 'shenzhen']
cityes_AQI = []
for i in range(4):
    filename = 'data/'+ citys[i] + '_AQI' + '_2018.csv' # 文件內容:"日期","質量等級","AQI指數","當天AQI排名","PM2.5"
    aqi_data = pd.read_csv(filename)

    get_data = aqi_data[['Date', 'AQI']] # 提取 "日期","AQI指數"兩列內容進行分析
    month_for_data = []
    for j in get_data['Date']:
        time = j.split('/')[1]
        month_for_data.append(time)
    aqi_data['Month'] = month_for_data # 獲取每行數據的月份

    # 求每個月AQI平均值
    month_data = aqi_data.groupby(['Month'])
    month_AQI = month_data['AQI'].agg(['mean'])
    month_AQI.reset_index(inplace=True)
    month_AQI_average = month_AQI.sort_index()

    # 獲取每個城市月均AQI的數據,轉化爲int數據類型
    month_AQI_data = np.array(month_AQI_average['mean'])
    month_AQI_data_int = ["{}".format(int(i)) for i in month_AQI_data]
    cityes_AQI.append(month_AQI_data_int)

months = ["{}".format(str(i) + '月') for i in range(1, 13)]

line = Line("2018年北上廣深AQI全年走勢圖", title_pos='center', title_top='0', width=800, height=400)
line.add("北京", months, cityes_AQI[0], line_color='red', legend_top='8%')
line.add("上海", months, cityes_AQI[1], line_color='purple', legend_top='8%')
line.add("廣州", months, cityes_AQI[2], line_color='blue', legend_top='8%')
line.add("深圳", months, cityes_AQI[3], line_color='orange', legend_top='8%')
line.render("result/2018年北上廣深AQI全年走勢圖.html")

image-20200412194325496

2018年北上廣深PM2.5走勢圖

import numpy as np
import pandas as pd
from pyecharts import Line

citys = ['beijing', 'shanghai', 'guangzhou', 'shenzhen']
cityes_PM = []
for i in range(4):
    filename ='data/'+  citys[i] + '_AQI' + '_2018.csv'  # 文件內容:"日期","質量等級","AQI指數","當天AQI排名","PM2.5"
    aqi_data = pd.read_csv(filename)

    get_data = aqi_data[['Date', 'PM']] # 提取 "日期","PM2.5"兩列內容進行分析
    month_for_data = []
    for j in get_data['Date']:
        time = j.split('/')[1]
        month_for_data.append(time)
    aqi_data['Month'] = month_for_data # 獲取每行數據的月份

    # 求每個月PM2.5平均值
    month_data = aqi_data.groupby(['Month'])
    month_PM = month_data['PM'].agg(['mean'])
    month_PM.reset_index(inplace=True)
    month_PM_average = month_PM.sort_index()

    # 獲取每個城市每個月AQI的數據,轉化爲int數據類型
    month_PM_data = np.array(month_PM_average['mean'])
    month_PM_data_int = ["{}".format(int(i)) for i in month_PM_data]
    cityes_PM.append(month_PM_data_int)

months = ["{}".format(str(i) + '月') for i in range(1, 13)]

line = Line("2018年北上廣深PM2.5全年走勢圖", title_pos='center', title_top='0', width=800, height=400)
line.add("北京", months, cityes_PM[0], line_color='red', legend_top='8%')
line.add("上海", months, cityes_PM[1], line_color='purple', legend_top='8%')
line.add("廣州", months, cityes_PM[2], line_color='blue', legend_top='8%')
line.add("深圳", months, cityes_PM[3], line_color='orange', legend_top='8%')
line.render("result/2018年北上廣深PM2.5全年走勢圖.html")

image-20200412203050148

2018年北上廣深一級空氣質量情況

import numpy as np
import pandas as pd
from pyecharts import Pie, Grid

citys = ['beijing', 'shanghai', 'guangzhou', 'shenzhen']
v = []
attrs = []
for i in range(4):
    filename = 'data/'+ citys[i] + '_AQI' + '_2018.csv'
    df = pd.read_csv(filename) #pd.read_csv(filename, header=None, names=["Date", "Quality_grade", "AQI", "AQI_rank", "PM"])

    Quality_grade_message = df.groupby(['Quality_grade'])
    Quality_grade_com = Quality_grade_message['Quality_grade'].agg(['count'])
    Quality_grade_com.reset_index(inplace=True)
    Quality_grade_com_last = Quality_grade_com.sort_values('count', ascending=False)

    Quality_grade_array = Quality_grade_com_last['Quality_grade']
    Quality_grade_array = np.array(Quality_grade_com_last['Quality_grade'])
    attrs.append(Quality_grade_array)
    Quality_grade_count = Quality_grade_com_last['count']
    Quality_grade_count = np.array(Quality_grade_com_last['count'])
    v.append(Quality_grade_count)

pie1 = Pie("北京", title_pos="28%", title_top="24%")
pie1.add("", attrs[0], v[0], radius=[20, 40], center=[30, 27], legend_pos="63%", legend_top="40%", legend_orient="vertical",is_label_show=True)

pie2 = Pie("上海", title_pos="52%", title_top="24%")
pie2.add("", attrs[1], v[1], radius=[20, 40], center=[54, 27], is_label_show=False, is_legend_show=False)

pie3 = Pie("廣州", title_pos='28%', title_top='77%')
pie3.add("", attrs[2], v[2], radius=[20, 40], center=[30, 80], is_label_show=False, is_legend_show=False)

pie4 = Pie("深圳", title_pos='52%', title_top='77%')
pie4.add("", attrs[3], v[3], radius=[20, 40], center=[54, 80], is_label_show=False, is_legend_show=False)

grid = Grid("2018年北上廣深全年空氣質量情況", width=1200)
grid.add(pie1)
grid.add(pie2)
grid.add(pie3)
grid.add(pie4)
grid.render('result/2018年北上廣深全年空氣質量情況.html')

image-20200412203158607

十一、關係數據可視化

直接上代碼

import ggplot as gp
# print(type(gp.mtcars))
# print(gp.mtcars)

#基本三個圖層
gp_data =gp.ggplot(gp.aes(x='mpg',y='wt'),data=gp.mtcars)#數據層
gp_geom = gp.geom_point(color="red")#幾何圖像層
gp_title = gp.ggtitle('mtcarts')#美學層
print(gp_data+gp_geom+gp_title)

image-20200422170808311

import ggplot as gp
gp_data =gp.ggplot(gp.aes(x='mpg',y='wt',color='factor(cyl)'),data=gp.mtcars)#數據層
gp_geom = gp.geom_point()#幾何圖像層
gp_title = gp.ggtitle('hhhh')#美學層
print(gp_data+gp_geom+gp_title)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Hr1Qd2TP-1589507131344)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20200422170941683.png)]

#讀數據繪製散點圖
import ggplot as gp
import pandas as pd
crime = pd.read_csv("data/crimeRatesByState2005.csv")
plot = gp.ggplot(gp.aes(x='murder', y='burglary'), data=crime)
points = gp.geom_point(color='red')
print(plot + points)

image-20200422171156826

查看關係

import ggplot as gp
import pandas as pd
crime = pd.read_csv("./data/crimeRatesByState2005.csv")
crime = crime[crime.state != "United States"]
crime = crime[crime.state != "District of Columbia"]
plot = gp.ggplot(gp.aes(x='murder', y='burglary'), data=crime)
points = gp.geom_point(color='red')
# smooth = gp.stat_smooth(method='loess', color='red')
print(plot + points )

image-20200422171144035

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
crime = pd.read_csv("./data/crimeRatesByState2005.csv")
crime = crime[crime.state != "United States"]
crime = crime[crime.state != "District of Columbia"]
crime = crime.drop(['state'], axis=1)
crime = crime.drop(['population'], axis=1)
g = sns.pairplot(crime, diag_kind="kde", kind="reg")
plt.show()

image-20200422171310627

氣泡圖
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
crime = pd.read_csv("./data/crimeRatesByState2005.csv")
crime2 = crime[crime.state != "United States"]
crime2 = crime2[crime2.state != "District of Columbia"]
s = list(crime2.population/10000)
colors = np.random.rand(len(list(crime2.murder)))
cm = plt.cm.get_cmap()
plt.scatter(x=list(crime2.murder), y=list(crime2.burglary), s=s, c=colors, cmap=cm, linewidth=0.5, alpha=0.5)
plt.xlabel("murder")
plt.ylabel("burglary")
plt.show()

image-20200422171435586

莖葉圖只適用於小數點後兩位的數據
from itertools import groupby
import pandas as pd
birth = pd.read_csv("./data/birth-rate.csv")
birth.dropna(subset=['2008'], inplace=True)
dirt = {}
data = list(round(birth['2008'], 1))
range_num = []
for k, g in groupby(sorted(data), key=lambda x: int(x)):
    lst = map(str, list(map(lambda y: divmod(int(y * 10), 10)[1], list(g))))
    dirt[k] = ' '.join(lst)
    range_num.append(k)
num = list(range(range_num[0], range_num[-1], 2))
for i in num:
   a = ""
   for k in sorted(dirt.keys()):
      if 0 <= k - i <= 1:
          a = a + ' ' + dirt[k]
      elif k- i > 1:
          break
   print(str(i).rjust(5), '|', a)

image-20200422171548701

# 直方圖
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 解決中文不能正常顯示的問題
titanic = pd.read_csv('./data/birth-rate.csv')
titanic.dropna(subset=['2008'], inplace=True)
plt.style.use('ggplot')
plt.hist(titanic['2008'], bins=15, color='steelblue', edgecolor='k', label="直方圖")
plt.tick_params(top='off', right='off')
plt.legend()
plt.show()

image-20200422171641931

# 密度圖
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
titanic = pd.read_csv('./data/birth-rate.csv')
titanic.dropna(subset=['2008'], inplace=True)
kde = mlab.GaussianKDE(titanic['2008'])
x2 = np.linspace(titanic['2008'].min(), titanic['2008'].max(), 1000)
line2 = plt.plot(x2, kde(x2), 'g-', linewidth=2)
plt.show()

image-20200422171721989

# 基於Python的直方圖結合密度圖的實現
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解決中文不能正常顯示的問題
titanic = pd.read_csv('./data/birth-rate.csv')
titanic.dropna(subset=['2008'], inplace=True)
plt.style.use('ggplot')
plt.hist(titanic['2008'], bins=np.arange(titanic['2008'].min(),
titanic['2008'].max(), 3), normed=True, color= 'steelblue', edgecolor='k')
plt.title(' 2008出生直方圖和密度圖')
plt.xlabel('出生率')
plt.ylabel('頻率')
kde = mlab.GaussianKDE(titanic['2008'])
x2 = np.linspace(titanic['2008'].min(), titanic['2008'].max(), 1000)
line2 = plt.plot(x2, kde(x2), 'g-', linewidth=2)
plt.tick_params(top='off', right='off')
plt.show()

image-20200422171822165

十二、空間數據可視化

1、地理座標系-Geo

1)地理座標系-散點圖

img

image-20200412204037551

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6GX3h1Xi-1589507131350)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20200412204055256.png)]

image-20200412204120320

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jR79ifu5-1589507131351)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20200412204144106.png)]

image-20200412204203676

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zTRCO0l0-1589507131353)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20200412204213897.png)]

image-20200412204221657

image-20200412204232652

image-20200412204247771

4、空間數據可視化實驗

實驗環境

  • pyecharts=1.7.2

各城市最低氣溫可視化

All_Data = []
ua = UserAgent(use_cache_server=False)
# 網頁的解析函數
def parse_page(url):
    headers = {
        'User-Agent': ua.random
    }
    response = requests.get(url, headers=headers)
    text = response.content.decode('utf-8')
    soup = BeautifulSoup(text, 'lxml')
    conMidtab = soup.find('div', {'class': 'conMidtab'})
    tables = conMidtab.find_all('table')
#     查看是否拿到了每個城市的天氣
    for table in tables:
        trs = table.find_all('tr')[2:]
        for index, tr in enumerate(trs):
            tds = tr.find_all('td')
            if len(tds) >= 8:
                city_td = tds[0]
                if index == 0:
                    city_td = tds[1]
    #             獲取標籤裏面的字符串屬性返回一個生成器,因此要轉化爲一個列表
                city = city_td.get_text()
                temp_td = tds[-2]
                min_temp = temp_td.get_text()
    #             將數據添加到列表
                All_Data.append({'城市': city, '最低氣溫': int(min_temp)})
def main():
    urls = [
        'http://www.weather.com.cn/textFC/hb.shtml',
        'http://www.weather.com.cn/textFC/db.shtml',
        'http://www.weather.com.cn/textFC/hz.shtml',
        'http://www.weather.com.cn/textFC/hn.shtml',
        'http://www.weather.com.cn/textFC/hd.shtml',
        'http://www.weather.com.cn/textFC/xb.shtml',
        'http://www.weather.com.cn/textFC/xn.shtml',
        'http://www.weather.com.cn/textFC/gat.shtml'
    ]
    for url in urls:
        parse_page(url)
    # 分析數據,根據最低氣溫進行排序
    All_Data.sort(key=lambda data: data['最低氣溫'])
    data = All_Data[0:10]  # 取出前10的最低氣溫及其城市
    return data
if __name__ == '__main__':
    datas = main()
    city = []
    temp = []
    plt.figure(figsize=(15, 9.27))
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標籤
    plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號
    for data in datas:
        city.append(data['城市'])
        temp.append(data['最低氣溫'])
    plt.bar(range(len(city)), temp, tick_label=city)
    plt.show()

img

import pandas as pd

def main():
    aqi_data = pd.read_csv('data/china_city_AQI.csv')
    print('基本信息:')
    print(aqi_data.info())

    print('數據預覽:')
    print(aqi_data.head())

    # 基本統計
    print('AQI最大值:', aqi_data['AQI'].max())
    print('AQI最小值:', aqi_data['AQI'].min())
    print('AQI均值:', aqi_data['AQI'].mean())

    # top10
    top10_cities = aqi_data.sort_values(by=['AQI']).head(10)
    print('空氣質量最好的10個城市:')
    print(top10_cities)

    # bottom10
    # bottom10_cities = aqi_data.sort_values(by=['AQI']).tail(10)
    bottom10_cities = aqi_data.sort_values(by=['AQI'], ascending=False).head(10)
    print('空氣質量最差的10個城市:')
    print(bottom10_cities)

    # 保存csv文件
    top10_cities.to_csv('data/top10_aqi.csv', index=False)
    bottom10_cities.to_csv('data/bottom10_aqi.csv', index=False)


if __name__ == '__main__':
    main()

img

def main():
    aqi_data = pd.read_csv('data/china_city_AQI.csv')
    print('基本信息:')
    print(aqi_data.info())

    print('數據預覽:')
    print(aqi_data.head())

    # 數據清洗
    # 只保留AQI>0的數據
    # filter_condition = aqi_data['AQI'] > 0
    # clean_aqi_data = aqi_data[filter_condition]

    clean_aqi_data = aqi_data[aqi_data['AQI'] > 0]

    # 基本統計
    print('AQI最大值:', clean_aqi_data['AQI'].max())
    print('AQI最小值:', clean_aqi_data['AQI'].min())
    print('AQI均值:', clean_aqi_data['AQI'].mean())

    # top50
    top50_cities = clean_aqi_data.sort_values(by=['AQI']).head(50)
    print(top50_cities)
    top50_cities.plot(kind='bar', x='City', y='AQI', title='空氣質量最好的50個城市',
                      figsize=(20, 10))
    plt.figure(figsize=(15, 9.27))
    plt.savefig('data/top50_aqi_bar.png')
    plt.show()


if __name__ == '__main__':
    main()

img

img

from pyecharts.globals import CurrentConfig, NotebookType
CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LAB
from pyecharts.globals import ThemeType
from pyecharts.charts import Bar
import pyecharts.options as opts

aqi_data = pd.read_csv('data/china_city_AQI.csv')
print('基本信息: ')
print(aqi_data.info())

print('數據預覽: ')
print(aqi_data.head())

#     數據清洗
#     只保留AQI>0的數據
clean_aqi_data = aqi_data[aqi_data['AQI']  > 0]

#     基本統計
print('AQI最大值:{}'.format(clean_aqi_data['AQI'].max()))
print('AQI最小值:{}'.format(clean_aqi_data['AQI'].min()))
print('AQI均值:{}'.format(clean_aqi_data['AQI'].mean()))

top50_cities = clean_aqi_data.sort_values(by=['AQI']).head(50)
bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
    .add_xaxis(top50_cities['City'].tolist())
    .add_yaxis('', top50_cities['AQI'].tolist(), label_opts=opts.LabelOpts(is_show=False), category_gap='50%')
    .set_global_opts(title_opts=opts.TitleOpts(title='空氣質量指數最優TOP50城市'),
                     xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=30, interval=0)),
                     datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_='inside')]
                    )
)
bar.load_javascript()
bar.render_notebook()

img

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章