這 40 個 Python 可視化圖表案例,強烈建議收藏!

大家好,我是小 F~

數據可視化是數據科學中關鍵的一步。

在以圖形方式表現某些數據時,Python 能夠提供很大的幫助。

不過有些小夥伴也會遇到不少問題,比如選擇何種圖表,以及如何製作,代碼如何編寫,這些都是問題!

今天給大家介紹一個 Python 圖表大全,40 個種類,總計約 400 個示例圖表。

分爲 7 個大系列,分佈、關係、排行、局部整體、時間序列、地理空間、流程。

文檔地址

https://www.python-graph-gallery.com

GitHub 地址

https://github.com/holtzy/The-Python-Graph-Gallery

給大家提供了示例及代碼,幾分鐘內就能構建一個你所需要的圖表。

下面就給大家介紹一下~

01. 小提琴圖

小提琴圖可以將一組或多組數據的數值變量分佈可視化。

相比有時會隱藏數據特徵的箱形圖相比,小提琴圖值得更多關注。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.violinplot(x=df["species"]y=df["sepal_length"])
plt.show()

使用 Seaborn 的 violinplot() 進行繪製,結果如下。

02. 核密度估計圖

核密度估計圖其實是對直方圖的一個自然拓展。

可以可視化一個或多個組的數值變量的分佈,非常適合大型數據集。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.kdeplot(df['sepal_width'])
plt.show()

使用 Seaborn 的 kdeplot() 進行繪製,結果如下。

03. 直方圖

直方圖,可視化一組或多組數據的分佈情況。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.distplot(a=df["sepal_length"]hist=True, kde=False, rug=False)
plt.show()

使用 Seaborn 的 distplot() 進行繪製,結果如下。

04. 箱形圖

箱形圖,可視化一組或多組數據的分佈情況。

可以快速獲得中位數、四分位數和異常值,但也隱藏數據集的各個數據點。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.boxplot(x=df["species"]y=df["sepal_length"])
plt.show()

使用 Seaborn 的 boxplot() 進行繪製,結果如下。

05. 山脊線圖

山脊線圖,總結幾組數據的分佈情況。

每個組都表示爲一個密度圖,每個密度圖相互重疊以更有效地利用空間。

import plotly.graph_objects as go
import numpy as np
import pandas as pd

# 讀取數據
temp = pd.read_csv('2016-weather-data-seattle.csv')
# 數據處理, 時間格式轉換
temp['year'] = pd.to_datetime(temp['Date']).dt.year

# 選擇幾年的數據展示即可
year_list = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
temp = temp[temp['year'].isin(year_list)]

# 繪製每年的直方圖,以年和平均溫度分組,並使用'count'函數進行彙總
temp = temp.groupby(['year''Mean_TemperatureC']).agg({'Mean_TemperatureC''count'}).rename(columns={'Mean_TemperatureC''count'}).reset_index()

# 使用Plotly繪製脊線圖,每個軌跡對應於特定年份的溫度分佈
# 將每年的數據(溫度和它們各自的計數)存儲在單獨的數組,並將其存儲在字典中以方便檢索
array_dict = {}
for year in year_list:
    # 每年平均溫度
    array_dict[f'x_{year}'] = temp[temp['year'] == year]['Mean_TemperatureC']
    # 每年溫度計數
    array_dict[f'y_{year}'] = temp[temp['year'] == year]['count']
    array_dict[f'y_{year}'] = (array_dict[f'y_{year}'] - array_dict[f'y_{year}'].min()) \
                              / (array_dict[f'y_{year}'].max() - array_dict[f'y_{year}'].min())

# 創建一個圖像對象
fig = go.Figure()
for index, year in enumerate(year_list):
    # 使用add_trace()繪製軌跡
    fig.add_trace(go.Scatter(
        x=[-20, 40]y=np.full(2, len(year_list) - index),
        mode='lines',
        line_color='white'))

    fig.add_trace(go.Scatter(
        x=array_dict[f'x_{year}'],
        y=array_dict[f'y_{year}'] + (len(year_list) - index) + 0.4,
        fill='tonexty',
        name=f'{year}'))

    # 添加文本
    fig.add_annotation(
        x=-20,
        y=len(year_list) - index,
        text=f'{year}',
        showarrow=False,
        yshift=10)

# 添加標題、圖例、xy軸參數
fig.update_layout(
    title='1950年~2010年西雅圖平均溫度',
    showlegend=False,
    xaxis=dict(title='單位: 攝氏度'),
    yaxis=dict(showticklabels=False)
)

# 跳轉網頁顯示
fig.show()

Seaborn 沒有專門的函數來繪製山脊線圖,可以多次調用 kdeplot() 來製作。

結果如下。

06. 散點圖

散點圖,顯示 2 個數值變量之間的關係。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.regplot(x=df["sepal_length"]y=df["sepal_width"])
plt.show()

使用 Seaborn 的 regplot() 進行繪製,結果如下。

07. 矩形熱力圖

矩形熱力圖,矩陣中的每個值都被表示爲一個顏色數據。

import seaborn as sns
import pandas as pd
import numpy as np

# Create a dataset
df = pd.DataFrame(np.random.random((5,5))columns=["a","b","c","d","e"])

# Default heatmap
p1 = sns.heatmap(df)

使用 Seaborn 的 heatmap() 進行繪製,結果如下。

08. 相關性圖

相關性圖或相關矩陣圖,分析每對數據變量之間的關係。

相關性可視化爲散點圖,對角線用直方圖或密度圖表示每個變量的分佈。

import seaborn as sns
import matplotlib.pyplot as plt

# 加載數據
df = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 繪圖顯示
sns.pairplot(df)
plt.show()

使用 Seaborn 的 pairplot() 進行繪製,結果如下。

09. 氣泡圖

氣泡圖其實就是一個散點圖,其中圓圈大小被映射到第三數值變量的值。

import matplotlib.pyplot as plt
import seaborn as sns
from gapminder import gapminder

# 導入數據
data = gapminder.loc[gapminder.year == 2007]

# 使用scatterplot創建氣泡圖
sns.scatterplot(data=data, x="gdpPercap"y="lifeExp"size="pop"legend=False, sizes=(20, 2000))

# 顯示
plt.show()

使用 Seaborn 的 scatterplot() 進行繪製,結果如下。

10. 連接散點圖

連接散點圖就是一個線圖,其中每個數據點由圓形或任何類型的標記展示。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 創建數據
df = pd.DataFrame({'x_axis': range(1, 10)'y_axis': np.random.randn(9) * 80 + range(1, 10)})

# 繪製顯示
plt.plot('x_axis''y_axis'data=df, linestyle='-'marker='o')
plt.show()

使用 Matplotlib 的 plot() 進行繪製,結果如下。

11. 二維密度圖

二維密度圖或二維直方圖,可視化兩個定量變量的組合分佈。

它們總是在 X 軸上表示一個變量,另一個在 Y 軸上,就像散點圖。

然後計算二維空間特定區域內的次數,並用顏色漸變表示。

形狀變化:六邊形 a hexbin chart,正方形 a 2d histogram,核密度 2d density plots 或 contour plots。

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kde

# 創建數據, 200個點
data = np.random.multivariate_normal([0, 0][[1, 0.5][0.5, 3]], 200)
x, y = data.T

# 創建畫布, 6個子圖
fig, axes = plt.subplots(ncols=6, nrows=1, figsize=(21, 5))

# 第一個子圖, 散點圖
axes[0].set_title('Scatterplot')
axes[0].plot(x, y, 'ko')

# 第二個子圖, 六邊形
nbins = 20
axes[1].set_title('Hexbin')
axes[1].hexbin(x, y, gridsize=nbins, cmap=plt.cm.BuGn_r)

# 2D 直方圖
axes[2].set_title('2D Histogram')
axes[2].hist2d(x, y, bins=nbins, cmap=plt.cm.BuGn_r)

# 高斯kde
k = kde.gaussian_kde(data.T)
xi, yi = np.mgrid[x.min():x.max():nbins * 1j, y.min():y.max():nbins * 1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))

# 密度圖
axes[3].set_title('Calculate Gaussian KDE')
axes[3].pcolormesh(xi, yi, zi.reshape(xi.shape)shading='auto'cmap=plt.cm.BuGn_r)

# 添加陰影
axes[4].set_title('2D Density with shading')
axes[4].pcolormesh(xi, yi, zi.reshape(xi.shape)shading='gouraud'cmap=plt.cm.BuGn_r)

# 添加輪廓
axes[5].set_title('Contour')
axes[5].pcolormesh(xi, yi, zi.reshape(xi.shape)shading='gouraud'cmap=plt.cm.BuGn_r)
axes[5].contour(xi, yi, zi.reshape(xi.shape))

plt.show()

使用 Matplotlib 和 scipy 進行繪製,結果如下。

12. 條形圖

條形圖表示多個明確的變量的數值關係。每個變量都爲一個條形。條形的大小代表其數值。

import numpy as np
import matplotlib.pyplot as plt

# 生成隨機數據
height = [3, 12, 5, 18, 45]
bars = ('A''B''C''D''E')
y_pos = np.arange(len(bars))

# 創建條形圖
plt.bar(y_pos, height)

# x軸標籤
plt.xticks(y_pos, bars)

# 顯示
plt.show()

使用 Matplotlib 的 bar() 進行繪製,結果如下。

13. 雷達圖

雷達圖,可以可視化多個定量變量的一個或多個系列的值。

每個變量都有自己的軸,所有軸都連接在圖形的中心。

import matplotlib.pyplot as plt
import pandas as pd
from math import pi

# 設置數據
df = pd.DataFrame({
    'group'['A''B''C''D'],
    'var1'[38, 1.5, 30, 4],
    'var2'[29, 10, 9, 34],
    'var3'[8, 39, 23, 24],
    'var4'[7, 31, 33, 14],
    'var5'[28, 15, 32, 14]
})

# 目標數量
categories = list(df)[1:]
N = len(categories)

# 角度
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

# 初始化
ax = plt.subplot(111, polar=True)

# 設置第一處
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)

# 添加背景信息
plt.xticks(angles[:-1], categories)
ax.set_rlabel_position(0)
plt.yticks([10, 20, 30]["10""20""30"]color="grey"size=7)
plt.ylim(0, 40)

# 添加數據圖

# 第一個
values = df.loc[0].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid'label="group A")
ax.fill(angles, values, 'b'alpha=0.1)

# 第二個
values = df.loc[1].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid'label="group B")
ax.fill(angles, values, 'r'alpha=0.1)

# 添加圖例
plt.legend(loc='upper right'bbox_to_anchor=(0.1, 0.1))

# 顯示
plt.show()

使用 Matplotlib 進行繪製,結果如下。

14. 詞雲圖

詞雲圖是文本數據的視覺表示。

單詞通常是單個的,每個單詞的重要性以字體大小或顏色表示。

from wordcloud import WordCloud
import matplotlib.pyplot as plt

# 添加詞語
text=("Python Python Python Matplotlib Chart Wordcloud Boxplot")

# 創建詞雲對象
wordcloud = WordCloud(width=480, height=480, margin=0).generate(text)

# 顯示詞雲圖
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.margins(x=0, y=0)
plt.show()

使用 wordcloud 進行繪製,結果如下。

15. 平行座標圖

一個平行座標圖,能夠比較不同系列相同屬性的數值情況。

Pandas 可能是繪製平行座標圖的最佳方式。

import seaborn as sns
import matplotlib.pyplot as plt
from pandas.plotting import parallel_coordinates

# 讀取數據
data = sns.load_dataset('iris'data_home='seaborn-data'cache=True)

# 創建圖表
parallel_coordinates(data, 'species'colormap=plt.get_cmap("Set2"))

# 顯示
plt.show()

使用 Pandas 的 parallel_coordinates() 進行繪製,結果如下。

16. 棒棒糖圖

棒棒糖圖其實就是柱狀圖的變形,顯示一個線段和一個圓。

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 創建數據
df = pd.DataFrame({'group': list(map(chr, range(65, 85)))'values': np.random.uniform(size=20) })

# 排序取值
ordered_df = df.sort_values(by='values')
my_range = range(1, len(df.index)+1)

# 創建圖表
plt.stem(ordered_df['values'])
plt.xticks(my_range, ordered_df['group'])

# 顯示
plt.show()

使用 Matplotlib 的 stem() 進行繪製,結果如下。

17. 徑向柱圖

徑向柱圖同樣也是條形圖的變形,但是使用極座標而不是直角座標系。

繪製起來有點麻煩,而且比柱狀圖準確度低,但更引人注目。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 生成數據
df = pd.DataFrame(
        {
            'Name'['item ' + str(i) for i in list(range(1, 51)) ],
            'Value': np.random.randint(low=10, high=100, size=50)
        })

# 排序
df = df.sort_values(by=['Value'])

# 初始化畫布
plt.figure(figsize=(20, 10))
ax = plt.subplot(111, polar=True)
plt.axis('off')

# 設置圖表參數
upperLimit = 100
lowerLimit = 30
labelPadding = 4

# 計算最大值
max = df['Value'].max()

# 數據下限10, 上限100
slope = (max - lowerLimit) / max
heights = slope * df.Value + lowerLimit

# 計算條形圖的寬度
width = 2*np.pi / len(df.index)

# 計算角度
indexes = list(range(1, len(df.index)+1))
angles = [element * width for element in indexes]

# 繪製條形圖
bars = ax.bar(
    x=angles,
    height=heights,
    width=width,
    bottom=lowerLimit,
    linewidth=2,
    edgecolor="white",
    color="#61a4b2",
)

# 添加標籤
for bar, angle, height, label in zip(bars,angles, heights, df["Name"]):

    # 旋轉
    rotation = np.rad2deg(angle)

    # 翻轉
    alignment = ""
    if angle >= np.pi/2 and angle < 3*np.pi/2:
        alignment = "right"
        rotation = rotation + 180
    else:
        alignment = "left"

    # 最後添加標籤
    ax.text(
        x=angle,
        y=lowerLimit + bar.get_height() + labelPadding,
        s=label,
        ha=alignment,
        va='center',
        rotation=rotation,
        rotation_mode="anchor")

plt.show()

使用 Matplotlib 進行繪製,結果如下。

18. 矩形樹圖

矩形樹圖是一種常見的表達『層級數據』『樹狀數據』的可視化形式。

它主要用面積的方式,便於突出展現出『樹』的各層級中重要的節點。

import matplotlib.pyplot as plt
import squarify
import pandas as pd

# 創建數據
df = pd.DataFrame({'nb_people'[8, 3, 4, 2]'group'["group A""group B""group C""group D"]})

# 繪圖顯示
squarify.plot(sizes=df['nb_people']label=df['group']alpha=.8 )
plt.axis('off')
plt.show()

使用 squarify 庫進行繪製,結果如下。

19. 維恩圖

維恩圖,顯示不同組之間所有可能的關係。

import matplotlib.pyplot as plt
from matplotlib_venn import venn2

# 創建圖表
venn2(subsets=(10, 5, 2)set_labels=('Group A''Group B'))

# 顯示
plt.show()

使用 matplotlib_venn 庫進行繪製,結果如下。

20. 圓環圖

圓環圖,本質上就是一個餅圖,中間切掉了一個區域。

import matplotlib.pyplot as plt

# 創建數據
size_of_groups = [12, 11, 3, 30]

# 生成餅圖
plt.pie(size_of_groups)

# 在中心添加一個圓, 生成環形圖
my_circle = plt.Circle((0, 0), 0.7, color='white')
p = plt.gcf()
p.gca().add_artist(my_circle)

plt.show()

使用 Matplotlib 進行繪製,結果如下。

21. 餅圖

餅圖,最常見的可視化圖表之一。

將圓劃分成一個個扇形區域,每個區域代表在整體中所佔的比例。

import matplotlib.pyplot as plt

# 創建數據
size_of_groups = [12, 11, 3, 30]

# 生成餅圖
plt.pie(size_of_groups)
plt.show()

使用 Matplotlib 進行繪製,結果如下。

22. 樹圖

樹圖主要用來可視化樹形數據結構,是一種特殊的層次類型,具有唯一的根節點,左子樹,和右子樹。

import pandas as pd
from matplotlib import pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage

# 讀取數據
df = pd.read_csv('mtcars.csv')
df = df.set_index('model')

# 計算每個樣本之間的距離
Z = linkage(df, 'ward')

# 繪圖
dendrogram(Z, leaf_rotation=90, leaf_font_size=8, labels=df.index)

# 顯示
plt.show()

使用 Scipy 進行繪製,結果如下。

23. 氣泡圖

氣泡圖,表示層次結構及數值大小。

import circlify
import matplotlib.pyplot as plt

# 創建畫布, 包含一個子圖
fig, ax = plt.subplots(figsize=(14, 14))

# 標題
ax.set_title('Repartition of the world population')

# 移除座標軸
ax.axis('off')

# 人口數據
data = [{'id''World''datum': 6964195249, 'children'[
              {'id'"North America"'datum': 450448697,
                  'children'[
                     {'id'"United States"'datum': 308865000},
                     {'id'"Mexico"'datum': 107550697},
                     {'id'"Canada"'datum': 34033000}
                   ]},
              {'id'"South America"'datum': 278095425,
                  'children'[
                     {'id'"Brazil"'datum': 192612000},
                     {'id'"Colombia"'datum': 45349000},
                     {'id'"Argentina"'datum': 40134425}
                   ]},
              {'id'"Europe"'datum': 209246682,
                  'children'[
                     {'id'"Germany"'datum': 81757600},
                     {'id'"France"'datum': 65447374},
                     {'id'"United Kingdom"'datum': 62041708}
                   ]},
              {'id'"Africa"'datum': 311929000,
                  'children'[
                     {'id'"Nigeria"'datum': 154729000},
                     {'id'"Ethiopia"'datum': 79221000},
                     {'id'"Egypt"'datum': 77979000}
                   ]},
              {'id'"Asia"'datum': 2745929500,
                  'children'[
                     {'id'"China"'datum': 1336335000},
                     {'id'"India"'datum': 1178225000},
                     {'id'"Indonesia"'datum': 231369500}
                   ]}
    ]}]

# 使用circlify()計算, 獲取圓的大小, 位置
circles = circlify.circlify(
    data,
    show_enclosure=False,
    target_enclosure=circlify.Circle(x=0, y=0, r=1)
)


lim = max(
    max(
        abs(circle.x) + circle.r,
        abs(circle.y) + circle.r,
    )
    for circle in circles
)
plt.xlim(-lim, lim)
plt.ylim(-lim, lim)

for circle in circles:
    if circle.level != 2:
        continue
    x, y, r = circle
    ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="lightblue"))

for circle in circles:
    if circle.level != 3:
        continue
    x, y, r = circle
    label = circle.ex["id"]
    ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="#69b3a2"))
    plt.annotate(label, (x, y)ha='center'color="white")

for circle in circles:
    if circle.level != 2:
        continue
    x, y, r = circle
    label = circle.ex["id"]
    plt.annotate(label, (x, y)va='center'ha='center'bbox=dict(facecolor='white'edgecolor='black'boxstyle='round'pad=.5))

plt.show()

使用 Circlify 進行繪製,結果如下。

24. 折線圖

折線圖是最常見的圖表類型之一。

將各個數據點標誌連接起來的圖表,用於展現數據的變化趨勢。

import matplotlib.pyplot as plt
import numpy as np

# 創建數據
values = np.cumsum(np.random.randn(1000, 1))

# 繪製圖表
plt.plot(values)
plt.show()

使用 Matplotlib 進行繪製,結果如下。

25. 面積圖

面積圖和折線圖非常相似,區別在於和 x 座標軸間是否被顏色填充。

import matplotlib.pyplot as plt

# 創建數據
x = range(1, 6)
y = [1, 4, 6, 8, 4]

# 生成圖表
plt.fill_between(x, y)
plt.show()

使用 Matplotlib 的 fill_between() 進行繪製,結果如下。

26. 堆疊面積圖

堆疊面積圖表示若干個數值變量的數值演變。

每個顯示在彼此的頂部,易於讀取總數,但較難準確讀取每個的值。

import matplotlib.pyplot as plt

# 創建數據
x = range(1, 6)
y1 = [1, 4, 6, 8, 9]
y2 = [2, 2, 7, 10, 12]
y3 = [2, 8, 5, 10, 6]

# 生成圖表
plt.stackplot(x, y1, y2, y3, labels=['A''B''C'])
plt.legend(loc='upper left')
plt.show()

使用 Matplotlib 的 stackplot() 進行繪製,結果如下。

27. 河流圖

河流圖是一種特殊的流圖, 它主要用來表示事件或主題等在一段時間內的變化。

圍繞着中心軸顯示,且邊緣是圓形的,從而形成流動的形狀。

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 添加數據
x = np.arange(1990, 2020)
y = [np.random.randint(0, 5, size=30) for _ in range(5)]


def gaussian_smooth(x, y, grid, sd):
    """平滑曲線"""
    weights = np.transpose([stats.norm.pdf(grid, m, sd) for m in x])
    weights = weights / weights.sum(0)
    return (weights * y).sum(1)


# 自定義顏色
COLORS = ["#D0D1E6""#A6BDDB""#74A9CF""#2B8CBE""#045A8D"]

# 創建畫布
fig, ax = plt.subplots(figsize=(10, 7))

# 生成圖表
grid = np.linspace(1985, 2025, num=500)
y_smoothed = [gaussian_smooth(x, y_, grid, 1) for y_ in y]
ax.stackplot(grid, y_smoothed, colors=COLORS, baseline="sym")

# 顯示
plt.show()

先使用 Matplotlib 繪製堆積圖,設置 stackplot() 的 baseline 參數,可將數據圍繞 x 軸展示。

再通過 scipy.interpolate 平滑曲線,最終結果如下。

28. 時間序列圖

時間序列圖是指能夠展示數值演變的所有圖表。

比如折線圖、柱狀圖、面積圖等等。

import numpy as np
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt

# 創建數據
my_count = ["France""Australia""Japan""USA""Germany""Congo""China""England""Spain""Greece""Marocco",
            "South Africa""Indonesia""Peru""Chili""Brazil"]
df = pd.DataFrame({
    "country": np.repeat(my_count, 10),
    "years": list(range(2000, 2010)) * 16,
    "value": np.random.rand(160)
})

# 創建網格
g = sns.FacetGrid(df, col='country'hue='country'col_wrap=4, )

# 添加曲線圖
g = g.map(plt.plot, 'years''value')

# 面積圖
g = g.map(plt.fill_between, 'years''value'alpha=0.2).set_titles("{col_name} country")

# 標題
g = g.set_titles("{col_name}")

# 總標題
plt.subplots_adjust(top=0.92)
g = g.fig.suptitle('Evolution of the value of stuff in 16 countries')

# 顯示
plt.show()

下面以一個時間序列面積圖爲例,顯示多組數據,結果如下。

29. 地圖

所有的地理空間數據分析應該都離不開地圖吧!

import pandas as pd
import folium

# 創建地圖對象
m = folium.Map(location=[20, 0]tiles="OpenStreetMap"zoom_start=2)

# 創建圖標數據
data = pd.DataFrame({
   'lon'[-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
   'lat'[-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97],
   'name'['Buenos Aires''Paris''melbourne''St Petersbourg''Abidjan''Montreal''Nairobi''Salvador'],
   'value'[10, 12, 40, 70, 23, 43, 100, 43]
}dtype=str)

# 添加信息
for i in range(0,len(data)):
    folium.Marker(
      location=[data.iloc[i]['lat'], data.iloc[i]['lon']],
      popup=data.iloc[i]['name'],
    ).add_to(m)

# 保存
m.save('map.html')

使用 Folium 繪製谷歌地圖風格的地圖,結果如下。

30. 等值域地圖

等值域地圖,相同數值範圍,着色相同。

import pandas as pd
import folium

# 創建地圖對象
m = folium.Map(location=[40, -95]zoom_start=4)

# 讀取數據
state_geo = f"us-states.json"
state_unemployment = f"US_Unemployment_Oct2012.csv"
state_data = pd.read_csv(state_unemployment)

folium.Choropleth(
    geo_data=state_geo,
    ,
    data=state_data,
    columns=["State""Unemployment"],
    key_on="feature.id",
    fill_color="YlGn",
    fill_opacity=0.7,
    line_opacity=.1,
    legend_,
).add_to(m)

folium.LayerControl().add_to(m)
# 保存
m.save('choropleth-map.html')

使用 Folium 的 choropleth() 進行繪製,結果如下。

31. 網格地圖

Hexbin 地圖,美國大選投票經常看見。

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt

# 讀取數據
file = "us_states_hexgrid.geojson.json"
geoData = gpd.read_file(file)
geoData['centroid'] = geoData['geometry'].apply(lambda x: x.centroid)

mariageData = pd.read_csv("State_mariage_rate.csv")
geoData['state'] = geoData['google_name'].str.replace(' \(United States\)','')

geoData = geoData.set_index('state').join(mariageData.set_index('state'))


# 初始化
fig, ax = plt.subplots(1, figsize=(6, 4))

# 繪圖
geoData.plot(
    ax=ax,
    column="y_2015",
    cmap="BuPu",
    norm=plt.Normalize(vmin=2, vmax=13),
    edgecolor='black',
    linewidth=.5
);

# 不顯示座標軸
ax.axis('off')

# 標題, 副標題,作者
ax.annotate('Mariage rate in the US'xy=(10, 340),  xycoords='axes pixels'horizontalalignment='left'verticalalignment='top'fontsize=14, color='black')
ax.annotate('Yes, people love to get married in Vegas'xy=(10, 320),  xycoords='axes pixels'horizontalalignment='left'verticalalignment='top'fontsize=11, color='#808080')
ax.annotate('xiao F'xy=(400, 0),  xycoords='axes pixels'horizontalalignment='left'verticalalignment='top'fontsize=8, color='#808080')

# 每個網格
for idx, row in geoData.iterrows():
    ax.annotate(
        s=row['iso3166_2'],
        xy=row['centroid'].coords[0],
        horizontalalignment='center',
        va='center',
        color="white"
    )

# 添加顏色
sm = plt.cm.ScalarMappable(cmap='BuPu'norm=plt.Normalize(vmin=2, vmax=13))
fig.colorbar(sm, orientation="horizontal"aspect=50, fraction=0.005, pad=);

# 顯示
plt.show()

使用 geopandas 和 matplotlib 進行繪製,結果如下。

32. 變形地圖

故名思義,就是形狀發生改變的地圖。

其中每個區域的形狀,會根據數值發生扭曲變化。

這裏沒有相關的代碼示例,直接上個圖好了。

33. 連接映射地圖

連接地圖可以顯示地圖上幾個位置之間的連接關係。

航空上經常用到的飛線圖,應該是這個的升級版。

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import pandas as pd

# 數據
cities = {
    'city'["Paris""Melbourne""Saint.Petersburg""Abidjan""Montreal""Nairobi""Salvador"],
    'lon'[2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
    'lat'[49, -38, 59.93, 5.33, 45.52, -1.29, -12.97]
}
df = pd.DataFrame(cities, columns=['city''lon''lat'])

# 創建地圖
m = Basemap(llcrnrlon=-179, llcrnrlat=-60, urcrnrlon=179, urcrnrlat=70, projection='merc')
m.drawmapboundary(fill_color='white'linewidth=0)
m.fillcontinents(color='#f2f2f2'alpha=0.7)
m.drawcoastlines(linewidth=0.1, color="white")

# 循環建立連接
for startIndex, startRow in df.iterrows():
    for endIndex in range(startIndex, len(df.index)):
        endRow = df.iloc[endIndex]
        m.drawgreatcircle(startRow.lon, startRow.lat, endRow.lon, endRow.lat, linewidth=1, color='#69b3a2');

# 添加城市名稱
for i, row in df.iterrows():
    plt.annotate(row.city, xy=m(row.lon + 3, row.lat)verticalalignment='center')

plt.show()

使用 basemap 繪製,結果如下。

34. 氣泡地圖

氣泡地圖,使用不同尺寸的圓來表示該地理座標的數值。

import folium
import pandas as pd

# 創建地圖對象
m = folium.Map(location=[20,0]tiles="OpenStreetMap"zoom_start=2)

# 座標點數據
data = pd.DataFrame({
   'lon'[-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
   'lat'[-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97],
   'name'['Buenos Aires''Paris''melbourne''St Petersbourg''Abidjan''Montreal''Nairobi''Salvador'],
   'value'[10, 12, 40, 70, 23, 43, 100, 43]
}dtype=str)

# 添加氣泡
for i in range(0, len(data)):
    folium.Circle(
      location=[data.iloc[i]['lat'], data.iloc[i]['lon']],
      popup=data.iloc[i]['name'],
      radius=float(data.iloc[i]['value'])*20000,
      color='crimson',
      fill=True,
      fill_color='crimson'
    ).add_to(m)

# 保存
m.save('bubble-map.html')

使用 Folium 的 Circle() 進行繪製,結果如下。

35. 和絃圖

和絃圖表示若干個實體 (節點) 之間的流或連接。

每個實體 (節點) 有圓形佈局外部的一個片段表示。

然後在每個實體之間繪製弧線,弧線的大小與流的關係成正比。

from chord import Chord

matrix = [
    [0, 5, 6, 4, 7, 4],
    [5, 0, 5, 4, 6, 5],
    [6, 5, 0, 4, 5, 5],
    [4, 4, 4, 0, 5, 5],
    [7, 6, 5, 5, 0, 4],
    [4, 5, 5, 5, 4, 0],
]

names = ["Action""Adventure""Comedy""Drama""Fantasy""Thriller"]

# 保存
Chord(matrix, names).to_html("chord-diagram.html")

使用 Chord 庫進行繪製,結果如下。

36. 網狀圖

網狀圖顯示的是一組實體之間的連接關係。

每個實體由一個節點表示,節點之間通過線段連接。

import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt

# 創建數據
ind1 = [5, 10, 3, 4, 8, 10, 12, 1, 9, 4]
ind5 = [1, 1, 13, 4, 18, 5, 2, 11, 3, 8]
df = pd.DataFrame(
    {'A': ind1, 'B': ind1 + np.random.randint(10, size=(10))'C': ind1 + np.random.randint(10, size=(10)),
     'D': ind1 + np.random.randint(5, size=(10))'E': ind1 + np.random.randint(5, size=(10))'F': ind5,
     'G': ind5 + np.random.randint(5, size=(10))'H': ind5 + np.random.randint(5, size=(10)),
     'I': ind5 + np.random.randint(5, size=(10))'J': ind5 + np.random.randint(5, size=(10))})

# 計算相關性
corr = df.corr()

# 轉換
links = corr.stack().reset_index()
links.columns = ['var1''var2''value']

# 保持相關性超過一個閾值, 刪除自相關性
links_filtered = links.loc[(links['value'] > 0.8) & (links['var1'] != links['var2'])]

# 生成圖
G = nx.from_pandas_edgelist(links_filtered, 'var1''var2')

# 繪製網絡
nx.draw(G, with_labels=True, node_color='orange'node_size=400, edge_color='black'linewidths=1, font_size=15)

# 顯示
plt.show()

使用 NetworkX 庫進行繪製,結果如下。

37. 桑基圖

桑基圖是一種特殊的流圖。

它主要用來表示原材料、能量等如何從初始形式經過中間過程的加工、轉化到達最終形式。

Plotly 可能是創建桑基圖的最佳工具,通過 Sankey() 在幾行代碼中獲得一個圖表。

import plotly.graph_objects as go
import json

# 讀取數據
with open('sankey_energy.json') as f:
    data = json.load(f)

# 透明度
opacity = 0.4
# 顏色
data['data'][0]['node']['color'] = ['rgba(255,0,255, 0.8)' if color == "magenta" else color for color in data['data'][0]['node']['color']]
data['data'][0]['link']['color'] = [data['data'][0]['node']['color'][src].replace("0.8", str(opacity))
                                    for src in data['data'][0]['link']['source']]

fig = go.Figure(data=[go.Sankey(
    valueformat=".0f",
    valuesuffix="TWh",
    # 點
    node=dict(
      pad=15,
      thickness=15,
      line=dict(color = "black"width = 0.5),
      label=data['data'][0]['node']['label'],
      color=data['data'][0]['node']['color']
    ),
    # 線
    link=dict(
      source=data['data'][0]['link']['source'],
      target=data['data'][0]['link']['target'],
      value=data['data'][0]['link']['value'],
      label=data['data'][0]['link']['label'],
      color=data['data'][0]['link']['color']
))])

fig.update_layout(title_text="Energy forecast for 2050<br>Source: Department of Energy & Climate Change, Tom Counsell via <a href='https://bost.ocks.org/mike/sankey/'>Mike Bostock</a>",
                  font_size=10)

# 保持
fig.write_html("sankey-diagram.html")

使用 Plotly 庫進行繪製,結果如下。

38. 弧線圖

弧線圖是一種特殊的網絡圖。

由代表實體的節點和顯示實體之間關係的弧線組成的。

在弧線圖中,節點沿單個軸顯示,節點間通過圓弧線進行連接。

目前還不知道如何通過 Python 來構建弧線圖,不過可以使用 R 或者 D3.js。

下面就來看一個通過 js 生成的弧線圖。

39. 環形佈局關係圖

可視化目標之間的關係,可以減少複雜網絡下觀察混亂。

和弧線圖一樣,也只能通 R 或者 D3.js 繪製。

D3.js 繪製的示例如下。

40. 動態圖表

動態圖表本質上就是顯示一系列靜態圖表。

可以描述目標從一種狀態到另一種狀態的變化。

import imageio
import pandas as pd
import matplotlib.pyplot as plt

# 讀取數據
data = pd.read_csv('gapminderData.csv')
# 更改格式
data['continent'] = pd.Categorical(data['continent'])

# 分辨率
dpi = 96

filenames = []
# 每年的數據
for i in data.year.unique():
    # 關閉交互式繪圖
    plt.ioff()

    # 初始化
    fig = plt.figure(figsize=(680 / dpi, 480 / dpi)dpi=dpi)

    # 篩選數據
    subsetData = data[data.year == i]

    # 生成散點氣泡圖
    plt.scatter(
        x=subsetData['lifeExp'],
        y=subsetData['gdpPercap'],
        s=subsetData['pop'] / 200000,
        c=subsetData['continent'].cat.codes,
        cmap="Accent"alpha=0.6, edgecolors="white"linewidth=2)

    # 添加相關信息
    plt.yscale('log')
    plt.xlabel("Life Expectancy")
    plt.ylabel("GDP per Capita")
    plt.title("Year: " + str(i))
    plt.ylim(0, 100000)
    plt.xlim(30, 90)

    # 保存
    filename = './images/' + str(i) + '.png'
    filenames.append(filename)
    plt.savefig(fname=filename, dpi=96)
    plt.gca()
    plt.close(fig)


# 生成GIF動態圖表
with imageio.get_writer('result.gif'mode='I'fps=5) as writer:
    for filename in filenames:
        image = imageio.imread(filename)
        writer.append_data(image)

以一個動態散點氣泡圖爲例,

先用 matplotlib 繪製圖表圖片,再通過 imageio 生成 GIF,結果如下。

好了,本期的分享就到此結束了。

其中使用到的可視化庫,大部分通過 pip install 即可完成安裝。

相關代碼及文件已上傳,回覆「可視化圖表」即可獲取。

有興趣的小夥伴,可以自行去實踐學習一下!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Dibp-nysRivcVsizPQfmeg