当前位置:   article > 正文

这40个Python可视化图表案例,强烈建议收藏!

python可视化

数据可视化是数据科学中关键的一步。

在以图形方式表现某些数据时,Python能够提供很大的帮助。

不过有些小伙伴也会遇到不少问题,比如选择何种图表,以及如何制作,代码如何编写,这些都是问题!

今天给大家介绍一个Python图表大全,40个种类,总计约400个示例图表。

分为7个大系列,分布、关系、排行、局部整体、时间序列、地理空间、流程。

10c8f87471eb25183d0ce4c68f223c08.png

文档地址:https://www.python-graph-gallery.com

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

给大家提供了示例及代码,几分钟内就能构建一个你所需要的图表。

下面就给大家介绍一下~

01. 小提琴图

小提琴图可以将一组或多组数据的数值变量分布可视化。

相比有时会隐藏数据特征的箱形图相比,小提琴图值得更多关注。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.violinplot(x=df["species"], y=df["sepal_length"])
  7. plt.show()

使用Seaborn的violinplot()进行绘制,结果如下。

94b32b56d5eceb78ab5b40a20f75051d.png

02. 核密度估计图

核密度估计图其实是对直方图的一个自然拓展。

可以可视化一个或多个组的数值变量的分布,非常适合大型数据集。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.kdeplot(df['sepal_width'])
  7. plt.show()

使用Seaborn的kdeplot()进行绘制,结果如下。

ca901b13376fa991f5c46455c5d742d9.png

03. 直方图

直方图,可视化一组或多组数据的分布情况。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.distplot(a=df["sepal_length"], hist=True, kde=False, rug=False)
  7. plt.show()

 使用Seaborn的distplot()进行绘制,结果如下。

61e98e55652f7fd4d73ccb33f59f57a0.png

04. 箱形图

箱形图,可视化一组或多组数据的分布情况。

可以快速获得中位数、四分位数和异常值,但也隐藏数据集的各个数据点。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.boxplot(x=df["species"], y=df["sepal_length"])
  7. plt.show()

使用Seaborn的boxplot()进行绘制,结果如下。

8b2a7a6963f677e5efa5874c2e35c2cd.png

05. 山脊线图

山脊线图,总结几组数据的分布情况。

每个组都表示为一个密度图,每个密度图相互重叠以更有效地利用空间。

  1. import plotly.graph_objects as go
  2. import numpy as np
  3. import pandas as pd
  4. # 读取数据
  5. temp = pd.read_csv('2016-weather-data-seattle.csv')
  6. # 数据处理, 时间格式转换
  7. temp['year'] = pd.to_datetime(temp['Date']).dt.year
  8. # 选择几年的数据展示即可
  9. year_list = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
  10. temp = temp[temp['year'].isin(year_list)]
  11. # 绘制每年的直方图,以年和平均温度分组,并使用'count'函数进行汇总
  12. temp = temp.groupby(['year', 'Mean_TemperatureC']).agg({'Mean_TemperatureC': 'count'}).rename(columns={'Mean_TemperatureC': 'count'}).reset_index()
  13. # 使用Plotly绘制脊线图,每个轨迹对应于特定年份的温度分布
  14. # 将每年的数据(温度和它们各自的计数)存储在单独的数组,并将其存储在字典中以方便检索
  15. array_dict = {}
  16. for year in year_list:
  17. # 每年平均温度
  18. array_dict[f'x_{year}'] = temp[temp['year'] == year]['Mean_TemperatureC']
  19. # 每年温度计数
  20. array_dict[f'y_{year}'] = temp[temp['year'] == year]['count']
  21. array_dict[f'y_{year}'] = (array_dict[f'y_{year}'] - array_dict[f'y_{year}'].min()) \
  22. / (array_dict[f'y_{year}'].max() - array_dict[f'y_{year}'].min())
  23. # 创建一个图像对象
  24. fig = go.Figure()
  25. for index, year in enumerate(year_list):
  26. # 使用add_trace()绘制轨迹
  27. fig.add_trace(go.Scatter(
  28. x=[-20, 40], y=np.full(2, len(year_list) - index),
  29. mode='lines',
  30. line_color='white'))
  31. fig.add_trace(go.Scatter(
  32. x=array_dict[f'x_{year}'],
  33. y=array_dict[f'y_{year}'] + (len(year_list) - index) + 0.4,
  34. fill='tonexty',
  35. name=f'{year}'))
  36. # 添加文本
  37. fig.add_annotation(
  38. x=-20,
  39. y=len(year_list) - index,
  40. text=f'{year}',
  41. showarrow=False,
  42. yshift=10)
  43. # 添加标题、图例、xy轴参数
  44. fig.update_layout(
  45. title='1950年~2010年西雅图平均温度',
  46. showlegend=False,
  47. xaxis=dict(title='单位: 摄氏度'),
  48. yaxis=dict(showticklabels=False)
  49. )
  50. # 跳转网页显示
  51. fig.show()

Seaborn没有专门的函数来绘制山脊线图,可以多次调用kdeplot()来制作。

结果如下。

c869050d5748d05ec7ece0866ddb92f5.png

06. 散点图

散点图,显示2个数值变量之间的关系。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.regplot(x=df["sepal_length"], y=df["sepal_width"])
  7. plt.show()

使用Seaborn的regplot()进行绘制,结果如下。

b8ffd2bc70ff0d3d570b4bebfd0c512a.png

07. 矩形热力图

矩形热力图,矩阵中的每个值都被表示为一个颜色数据。

  1. import seaborn as sns
  2. import pandas as pd
  3. import numpy as np
  4. # Create a dataset
  5. df = pd.DataFrame(np.random.random((5,5)), columns=["a","b","c","d","e"])
  6. # Default heatmap
  7. p1 = sns.heatmap(df)

使用Seaborn的heatmap()进行绘制,结果如下。

00a71232514c7305905686ebec3ee758.png

08. 相关性图

相关性图或相关矩阵图,分析每对数据变量之间的关系。

相关性可视化为散点图,对角线用直方图或密度图表示每个变量的分布。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 加载数据
  4. df = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  5. # 绘图显示
  6. sns.pairplot(df)
  7. plt.show()

使用Seaborn的pairplot()进行绘制,结果如下。

a281cf1a63d058885dc3197ec72d84df.png

09. 气泡图

气泡图其实就是一个散点图,其中圆圈大小被映射到第三数值变量的值。

  1. import matplotlib.pyplot as plt
  2. import seaborn as sns
  3. from gapminder import gapminder
  4. # 导入数据
  5. data = gapminder.loc[gapminder.year == 2007]
  6. # 使用scatterplot创建气泡图
  7. sns.scatterplot(data=data, x="gdpPercap", y="lifeExp", size="pop", legend=False, sizes=(20, 2000))
  8. # 显示
  9. plt.show()

使用Seaborn的scatterplot()进行绘制,结果如下。

94e8cf2436f246982c8243c3f4a78c3c.png

10. 连接散点图

连接散点图就是一个线图,其中每个数据点由圆形或任何类型的标记展示。

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import pandas as pd
  4. # 创建数据
  5. df = pd.DataFrame({'x_axis': range(1, 10), 'y_axis': np.random.randn(9) * 80 + range(1, 10)})
  6. # 绘制显示
  7. plt.plot('x_axis', 'y_axis', data=df, linestyle='-', marker='o')
  8. plt.show()

使用Matplotlib的plot()进行绘制,结果如下。

a26fe1b3f77404b938da28222ec9b620.png

11. 二维密度图

二维密度图或二维直方图,可视化两个定量变量的组合分布。

它们总是在X轴上表示一个变量,另一个在Y轴上,就像散点图。

然后计算二维空间特定区域内的次数,并用颜色渐变表示。

形状变化:六边形a hexbin chart,正方形a 2d histogram,核密度2d density plots或contour plots。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from scipy.stats import kde
  4. # 创建数据, 200个点
  5. data = np.random.multivariate_normal([0, 0], [[1, 0.5], [0.5, 3]], 200)
  6. x, y = data.T
  7. # 创建画布, 6个子图
  8. fig, axes = plt.subplots(ncols=6, nrows=1, figsize=(21, 5))
  9. # 第一个子图, 散点图
  10. axes[0].set_title('Scatterplot')
  11. axes[0].plot(x, y, 'ko')
  12. # 第二个子图, 六边形
  13. nbins = 20
  14. axes[1].set_title('Hexbin')
  15. axes[1].hexbin(x, y, gridsize=nbins, cmap=plt.cm.BuGn_r)
  16. # 2D 直方图
  17. axes[2].set_title('2D Histogram')
  18. axes[2].hist2d(x, y, bins=nbins, cmap=plt.cm.BuGn_r)
  19. # 高斯kde
  20. k = kde.gaussian_kde(data.T)
  21. xi, yi = np.mgrid[x.min():x.max():nbins * 1j, y.min():y.max():nbins * 1j]
  22. zi = k(np.vstack([xi.flatten(), yi.flatten()]))
  23. # 密度图
  24. axes[3].set_title('Calculate Gaussian KDE')
  25. axes[3].pcolormesh(xi, yi, zi.reshape(xi.shape), shading='auto', cmap=plt.cm.BuGn_r)
  26. # 添加阴影
  27. axes[4].set_title('2D Density with shading')
  28. axes[4].pcolormesh(xi, yi, zi.reshape(xi.shape), shading='gouraud', cmap=plt.cm.BuGn_r)
  29. # 添加轮廓
  30. axes[5].set_title('Contour')
  31. axes[5].pcolormesh(xi, yi, zi.reshape(xi.shape), shading='gouraud', cmap=plt.cm.BuGn_r)
  32. axes[5].contour(xi, yi, zi.reshape(xi.shape))
  33. plt.show()

使用Matplotlib和scipy进行绘制,结果如下。

7381ac29cf801a6f0cf59e259a76ef9e.png

12. 条形图

条形图表示多个明确的变量的数值关系。每个变量都为一个条形。条形的大小代表其数值。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. # 生成随机数据
  4. height = [3, 12, 5, 18, 45]
  5. bars = ('A', 'B', 'C', 'D', 'E')
  6. y_pos = np.arange(len(bars))
  7. # 创建条形图
  8. plt.bar(y_pos, height)
  9. # x轴标签
  10. plt.xticks(y_pos, bars)
  11. # 显示
  12. plt.show()

使用Matplotlib的bar()进行绘制,结果如下。

592dd86dd647b103346df6d49242b487.png

13. 雷达图

雷达图,可以可视化多个定量变量的一个或多个系列的值。

每个变量都有自己的轴,所有轴都连接在图形的中心。

  1. import matplotlib.pyplot as plt
  2. import pandas as pd
  3. from math import pi
  4. # 设置数据
  5. df = pd.DataFrame({
  6. 'group': ['A', 'B', 'C', 'D'],
  7. 'var1': [38, 1.5, 30, 4],
  8. 'var2': [29, 10, 9, 34],
  9. 'var3': [8, 39, 23, 24],
  10. 'var4': [7, 31, 33, 14],
  11. 'var5': [28, 15, 32, 14]
  12. })
  13. # 目标数量
  14. categories = list(df)[1:]
  15. N = len(categories)
  16. # 角度
  17. angles = [n / float(N) * 2 * pi for n in range(N)]
  18. angles += angles[:1]
  19. # 初始化
  20. ax = plt.subplot(111, polar=True)
  21. # 设置第一处
  22. ax.set_theta_offset(pi / 2)
  23. ax.set_theta_direction(-1)
  24. # 添加背景信息
  25. plt.xticks(angles[:-1], categories)
  26. ax.set_rlabel_position(0)
  27. plt.yticks([10, 20, 30], ["10", "20", "30"], color="grey", size=7)
  28. plt.ylim(0, 40)
  29. # 添加数据图
  30. # 第一个
  31. values = df.loc[0].drop('group').values.flatten().tolist()
  32. values += values[:1]
  33. ax.plot(angles, values, linewidth=1, linestyle='solid', label="group A")
  34. ax.fill(angles, values, 'b', alpha=0.1)
  35. # 第二个
  36. values = df.loc[1].drop('group').values.flatten().tolist()
  37. values += values[:1]
  38. ax.plot(angles, values, linewidth=1, linestyle='solid', label="group B")
  39. ax.fill(angles, values, 'r', alpha=0.1)
  40. # 添加图例
  41. plt.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))
  42. # 显示
  43. plt.show()

使用Matplotlib进行绘制,结果如下。

6eb0f789bda5d079028086e9fdf8d64b.png

14. 词云图

词云图是文本数据的视觉表示。

单词通常是单个的,每个单词的重要性以字体大小或颜色表示。

  1. from wordcloud import WordCloud
  2. import matplotlib.pyplot as plt
  3. # 添加词语
  4. text=("Python Python Python Matplotlib Chart Wordcloud Boxplot")
  5. # 创建词云对象
  6. wordcloud = WordCloud(width=480, height=480, margin=0).generate(text)
  7. # 显示词云图
  8. plt.imshow(wordcloud, interpolation='bilinear')
  9. plt.axis("off")
  10. plt.margins(x=0, y=0)
  11. plt.show()

使用wordcloud进行绘制,结果如下。

94f6f58444f81abf4d23af9bdde23c5d.png

15. 平行座标图

一个平行座标图,能够比较不同系列相同属性的数值情况。

Pandas可能是绘制平行坐标图的最佳方式。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. from pandas.plotting import parallel_coordinates
  4. # 读取数据
  5. data = sns.load_dataset('iris', data_home='seaborn-data', cache=True)
  6. # 创建图表
  7. parallel_coordinates(data, 'species', colormap=plt.get_cmap("Set2"))
  8. # 显示
  9. plt.show()

使用Pandas的parallel_coordinates()进行绘制,结果如下。

d4260838020ec7f2d47032064df580c5.png

16. 棒棒糖图

棒棒糖图其实就是柱状图的变形,显示一个线段和一个圆。

  1. import matplotlib.pyplot as plt
  2. import pandas as pd
  3. import numpy as np
  4. # 创建数据
  5. df = pd.DataFrame({'group': list(map(chr, range(65, 85))), 'values': np.random.uniform(size=20) })
  6. # 排序取值
  7. ordered_df = df.sort_values(by='values')
  8. my_range = range(1, len(df.index)+1)
  9. # 创建图表
  10. plt.stem(ordered_df['values'])
  11. plt.xticks(my_range, ordered_df['group'])
  12. # 显示
  13. plt.show()

使用Matplotlib的stem()进行绘制,结果如下。

1842cf7288a821d4015e9c3cfbdc15bc.png

17. 径向柱图

径向柱图同样也是条形图的变形,但是使用极坐标而不是直角坐标系。

绘制起来有点麻烦,而且比柱状图准确度低,但更引人注目。

  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. # 生成数据
  5. df = pd.DataFrame(
  6. {
  7. 'Name': ['item ' + str(i) for i in list(range(1, 51)) ],
  8. 'Value': np.random.randint(low=10, high=100, size=50)
  9. })
  10. # 排序
  11. df = df.sort_values(by=['Value'])
  12. # 初始化画布
  13. plt.figure(figsize=(20, 10))
  14. ax = plt.subplot(111, polar=True)
  15. plt.axis('off')
  16. # 设置图表参数
  17. upperLimit = 100
  18. lowerLimit = 30
  19. labelPadding = 4
  20. # 计算最大值
  21. max = df['Value'].max()
  22. # 数据下限10, 上限100
  23. slope = (max - lowerLimit) / max
  24. heights = slope * df.Value + lowerLimit
  25. # 计算条形图的宽度
  26. width = 2*np.pi / len(df.index)
  27. # 计算角度
  28. indexes = list(range(1, len(df.index)+1))
  29. angles = [element * width for element in indexes]
  30. # 绘制条形图
  31. bars = ax.bar(
  32. x=angles,
  33. height=heights,
  34. width=width,
  35. bottom=lowerLimit,
  36. linewidth=2,
  37. edgecolor="white",
  38. color="#61a4b2",
  39. )
  40. # 添加标签
  41. for bar, angle, height, label in zip(bars,angles, heights, df["Name"]):
  42. # 旋转
  43. rotation = np.rad2deg(angle)
  44. # 翻转
  45. alignment = ""
  46. if angle >= np.pi/2 and angle < 3*np.pi/2:
  47. alignment = "right"
  48. rotation = rotation + 180
  49. else:
  50. alignment = "left"
  51. # 最后添加标签
  52. ax.text(
  53. x=angle,
  54. y=lowerLimit + bar.get_height() + labelPadding,
  55. s=label,
  56. ha=alignment,
  57. va='center',
  58. rotation=rotation,
  59. rotation_mode="anchor")
  60. plt.show()

使用Matplotlib进行绘制,结果如下。

235566ccbc22def4105f76fc0777c68a.png

18. 矩形树图

矩形树图是一种常见的表达『层级数据』『树状数据』的可视化形式。

它主要用面积的方式,便于突出展现出『树』的各层级中重要的节点。

  1. import matplotlib.pyplot as plt
  2. import squarify
  3. import pandas as pd
  4. # 创建数据
  5. df = pd.DataFrame({'nb_people': [8, 3, 4, 2], 'group': ["group A", "group B", "group C", "group D"]})
  6. # 绘图显示
  7. squarify.plot(sizes=df['nb_people'], label=df['group'], alpha=.8 )
  8. plt.axis('off')
  9. plt.show()

使用squarify库进行绘制,结果如下。

69bef74d7c22bef00369910c7538f0a2.png

19. 维恩图

维恩图,显示不同组之间所有可能的关系。

  1. import matplotlib.pyplot as plt
  2. from matplotlib_venn import venn2
  3. # 创建图表
  4. venn2(subsets=(10, 5, 2), set_labels=('Group A', 'Group B'))
  5. # 显示
  6. plt.show()

使用matplotlib_venn库进行绘制,结果如下。

084c27e7997a1ba8435c40e8eaaa87d8.png

20. 圆环图

圆环图,本质上就是一个饼图,中间切掉了一个区域。

  1. import matplotlib.pyplot as plt
  2. # 创建数据
  3. size_of_groups = [12, 11, 3, 30]
  4. # 生成饼图
  5. plt.pie(size_of_groups)
  6. # 在中心添加一个圆, 生成环形图
  7. my_circle = plt.Circle((0, 0), 0.7, color='white')
  8. p = plt.gcf()
  9. p.gca().add_artist(my_circle)
  10. plt.show()

使用Matplotlib进行绘制,结果如下。

a5501d237c301a920d67a21ffa56f560.png

21. 饼图

饼图,最常见的可视化图表之一。

将圆划分成一个个扇形区域,每个区域代表在整体中所占的比例。

  1. import matplotlib.pyplot as plt
  2. # 创建数据
  3. size_of_groups = [12, 11, 3, 30]
  4. # 生成饼图
  5. plt.pie(size_of_groups)
  6. plt.show()

使用Matplotlib进行绘制,结果如下。

41263bb38e3c63a363518c24240c5441.png

22. 树图

树图主要用来可视化树形数据结构,是一种特殊的层次类型,具有唯一的根节点,左子树,和右子树。

  1. import pandas as pd
  2. from matplotlib import pyplot as plt
  3. from scipy.cluster.hierarchy import dendrogram, linkage
  4. # 读取数据
  5. df = pd.read_csv('mtcars.csv')
  6. df = df.set_index('model')
  7. # 计算每个样本之间的距离
  8. Z = linkage(df, 'ward')
  9. # 绘图
  10. dendrogram(Z, leaf_rotation=90, leaf_font_size=8, labels=df.index)
  11. # 显示
  12. plt.show()

使用Scipy进行绘制,结果如下。

a8757b6d66cbc1f515ee0d2545ee526b.png

23. 气泡图

气泡图,表示层次结构及数值大小。

  1. import circlify
  2. import matplotlib.pyplot as plt
  3. # 创建画布, 包含一个子图
  4. fig, ax = plt.subplots(figsize=(14, 14))
  5. # 标题
  6. ax.set_title('Repartition of the world population')
  7. # 移除坐标轴
  8. ax.axis('off')
  9. # 人口数据
  10. data = [{'id': 'World', 'datum': 6964195249, 'children': [
  11. {'id': "North America", 'datum': 450448697,
  12. 'children': [
  13. {'id': "United States", 'datum': 308865000},
  14. {'id': "Mexico", 'datum': 107550697},
  15. {'id': "Canada", 'datum': 34033000}
  16. ]},
  17. {'id': "South America", 'datum': 278095425,
  18. 'children': [
  19. {'id': "Brazil", 'datum': 192612000},
  20. {'id': "Colombia", 'datum': 45349000},
  21. {'id': "Argentina", 'datum': 40134425}
  22. ]},
  23. {'id': "Europe", 'datum': 209246682,
  24. 'children': [
  25. {'id': "Germany", 'datum': 81757600},
  26. {'id': "France", 'datum': 65447374},
  27. {'id': "United Kingdom", 'datum': 62041708}
  28. ]},
  29. {'id': "Africa", 'datum': 311929000,
  30. 'children': [
  31. {'id': "Nigeria", 'datum': 154729000},
  32. {'id': "Ethiopia", 'datum': 79221000},
  33. {'id': "Egypt", 'datum': 77979000}
  34. ]},
  35. {'id': "Asia", 'datum': 2745929500,
  36. 'children': [
  37. {'id': "China", 'datum': 1336335000},
  38. {'id': "India", 'datum': 1178225000},
  39. {'id': "Indonesia", 'datum': 231369500}
  40. ]}
  41. ]}]
  42. # 使用circlify()计算, 获取圆的大小, 位置
  43. circles = circlify.circlify(
  44. data,
  45. show_enclosure=False,
  46. target_enclosure=circlify.Circle(x=0, y=0, r=1)
  47. )
  48. lim = max(
  49. max(
  50. abs(circle.x) + circle.r,
  51. abs(circle.y) + circle.r,
  52. )
  53. for circle in circles
  54. )
  55. plt.xlim(-lim, lim)
  56. plt.ylim(-lim, lim)
  57. for circle in circles:
  58. if circle.level != 2:
  59. continue
  60. x, y, r = circle
  61. ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="lightblue"))
  62. for circle in circles:
  63. if circle.level != 3:
  64. continue
  65. x, y, r = circle
  66. label = circle.ex["id"]
  67. ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="#69b3a2"))
  68. plt.annotate(label, (x, y), ha='center', color="white")
  69. for circle in circles:
  70. if circle.level != 2:
  71. continue
  72. x, y, r = circle
  73. label = circle.ex["id"]
  74. plt.annotate(label, (x, y), va='center', ha='center', bbox=dict(facecolor='white', edgecolor='black', boxstyle='round', pad=.5))
  75. plt.show()

使用Circlify进行绘制,结果如下。

5200e7cf1a4d25560f1f24abe7b78689.png

24. 折线图

折线图是最常见的图表类型之一。

将各个数据点标志连接起来的图表,用于展现数据的变化趋势。

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. values = np.cumsum(np.random.randn(1000, 1))
  5. # 绘制图表
  6. plt.plot(values)
  7. plt.show()

使用Matplotlib进行绘制,结果如下。

3300117aedb3af8ed3bb4bb1c524cdb0.png

25. 面积图

面积图和折线图非常相似,区别在于和x坐标轴间是否被颜色填充。

  1. import matplotlib.pyplot as plt
  2. # 创建数据
  3. x = range(1, 6)
  4. y = [1, 4, 6, 8, 4]
  5. # 生成图表
  6. plt.fill_between(x, y)
  7. plt.show()

使用Matplotlib的fill_between()进行绘制,结果如下。

b5d3cdba052058d381dcdcd7c28cb680.png

26. 堆叠面积图

堆叠面积图表示若干个数值变量的数值演变。

每个显示在彼此的顶部,易于读取总数,但较难准确读取每个的值。

  1. import matplotlib.pyplot as plt
  2. # 创建数据
  3. x = range(1, 6)
  4. y1 = [1, 4, 6, 8, 9]
  5. y2 = [2, 2, 7, 10, 12]
  6. y3 = [2, 8, 5, 10, 6]
  7. # 生成图表
  8. plt.stackplot(x, y1, y2, y3, labels=['A', 'B', 'C'])
  9. plt.legend(loc='upper left')
  10. plt.show()

使用Matplotlib的stackplot()进行绘制,结果如下。

22e5f8625b45d820bcaf069168096521.png

27. 河流图

河流图是一种特殊的流图, 它主要用来表示事件或主题等在一段时间内的变化。

围绕着中心轴显示,且边缘是圆形的,从而形成流动的形状。

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from scipy import stats
  4. # 添加数据
  5. x = np.arange(1990, 2020)
  6. y = [np.random.randint(0, 5, size=30) for _ in range(5)]
  7. def gaussian_smooth(x, y, grid, sd):
  8. """平滑曲线"""
  9. weights = np.transpose([stats.norm.pdf(grid, m, sd) for m in x])
  10. weights = weights / weights.sum(0)
  11. return (weights * y).sum(1)
  12. # 自定义颜色
  13. COLORS = ["#D0D1E6", "#A6BDDB", "#74A9CF", "#2B8CBE", "#045A8D"]
  14. # 创建画布
  15. fig, ax = plt.subplots(figsize=(10, 7))
  16. # 生成图表
  17. grid = np.linspace(1985, 2025, num=500)
  18. y_smoothed = [gaussian_smooth(x, y_, grid, 1) for y_ in y]
  19. ax.stackplot(grid, y_smoothed, colors=COLORS, baseline="sym")
  20. # 显示
  21. plt.show()

先使用Matplotlib绘制堆积图,设置stackplot()的baseline参数,可将数据围绕x轴展示。

再通过scipy.interpolate平滑曲线,最终结果如下。

f9a2c71874b1030b59f09177f29ba618.png

28. 时间序列图

时间序列图是指能够展示数值演变的所有图表。

比如折线图、柱状图、面积图等等。

  1. import numpy as np
  2. import seaborn as sns
  3. import pandas as pd
  4. import matplotlib.pyplot as plt
  5. # 创建数据
  6. my_count = ["France", "Australia", "Japan", "USA", "Germany", "Congo", "China", "England", "Spain", "Greece", "Marocco",
  7. "South Africa", "Indonesia", "Peru", "Chili", "Brazil"]
  8. df = pd.DataFrame({
  9. "country": np.repeat(my_count, 10),
  10. "years": list(range(2000, 2010)) * 16,
  11. "value": np.random.rand(160)
  12. })
  13. # 创建网格
  14. g = sns.FacetGrid(df, col='country', hue='country', col_wrap=4, )
  15. # 添加曲线图
  16. g = g.map(plt.plot, 'years', 'value')
  17. # 面积图
  18. g = g.map(plt.fill_between, 'years', 'value', alpha=0.2).set_titles("{col_name} country")
  19. # 标题
  20. g = g.set_titles("{col_name}")
  21. # 总标题
  22. plt.subplots_adjust(top=0.92)
  23. g = g.fig.suptitle('Evolution of the value of stuff in 16 countries')
  24. # 显示
  25. plt.show()

下面以一个时间序列面积图为例,显示多组数据,结果如下。

61037f9e96b75a11295efab83383e156.png

29. 地图

所有的地理空间数据分析应该都离不开地图吧!

  1. import pandas as pd
  2. import folium
  3. # 创建地图对象
  4. m = folium.Map(location=[20, 0], tiles="OpenStreetMap", zoom_start=2)
  5. # 创建图标数据
  6. data = pd.DataFrame({
  7. 'lon': [-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
  8. 'lat': [-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97],
  9. 'name': ['Buenos Aires', 'Paris', 'melbourne', 'St Petersbourg', 'Abidjan', 'Montreal', 'Nairobi', 'Salvador'],
  10. 'value': [10, 12, 40, 70, 23, 43, 100, 43]
  11. }, dtype=str)
  12. # 添加信息
  13. for i in range(0,len(data)):
  14. folium.Marker(
  15. location=[data.iloc[i]['lat'], data.iloc[i]['lon']],
  16. popup=data.iloc[i]['name'],
  17. ).add_to(m)
  18. # 保存
  19. m.save('map.html')

使用Folium绘制谷歌地图风格的地图,结果如下。

274fae699a42456f2950904e6ba6af9f.png

30. 等值域地图

等值域地图,相同数值范围,着色相同。

  1. import pandas as pd
  2. import folium
  3. # 创建地图对象
  4. m = folium.Map(location=[40, -95], zoom_start=4)
  5. # 读取数据
  6. state_geo = f"us-states.json"
  7. state_unemployment = f"US_Unemployment_Oct2012.csv"
  8. state_data = pd.read_csv(state_unemployment)
  9. folium.Choropleth(
  10. geo_data=state_geo,
  11. name="choropleth",
  12. data=state_data,
  13. columns=["State", "Unemployment"],
  14. key_on="feature.id",
  15. fill_color="YlGn",
  16. fill_opacity=0.7,
  17. line_opacity=.1,
  18. legend_name="Unemployment Rate (%)",
  19. ).add_to(m)
  20. folium.LayerControl().add_to(m)
  21. # 保存
  22. m.save('choropleth-map.html')

使用Folium的choropleth()进行绘制,结果如下。

66cd29a6ebf3634a36b0c186fbeb8f87.png

31. 网格地图

Hexbin地图,美国大选投票经常看见。

  1. import pandas as pd
  2. import geopandas as gpd
  3. import matplotlib.pyplot as plt
  4. # 读取数据
  5. file = "us_states_hexgrid.geojson.json"
  6. geoData = gpd.read_file(file)
  7. geoData['centroid'] = geoData['geometry'].apply(lambda x: x.centroid)
  8. mariageData = pd.read_csv("State_mariage_rate.csv")
  9. geoData['state'] = geoData['google_name'].str.replace(' \(United States\)','')
  10. geoData = geoData.set_index('state').join(mariageData.set_index('state'))
  11. # 初始化
  12. fig, ax = plt.subplots(1, figsize=(6, 4))
  13. # 绘图
  14. geoData.plot(
  15. ax=ax,
  16. column="y_2015",
  17. cmap="BuPu",
  18. norm=plt.Normalize(vmin=2, vmax=13),
  19. edgecolor='black',
  20. linewidth=.5
  21. );
  22. # 不显示坐标轴
  23. ax.axis('off')
  24. # 标题, 副标题,作者
  25. ax.annotate('Mariage rate in the US', xy=(10, 340), xycoords='axes pixels', horizontalalignment='left', verticalalignment='top', fontsize=14, color='black')
  26. ax.annotate('Yes, people love to get married in Vegas', xy=(10, 320), xycoords='axes pixels', horizontalalignment='left', verticalalignment='top', fontsize=11, color='#808080')
  27. ax.annotate('xiao F', xy=(400, 0), xycoords='axes pixels', horizontalalignment='left', verticalalignment='top', fontsize=8, color='#808080')
  28. # 每个网格
  29. for idx, row in geoData.iterrows():
  30. ax.annotate(
  31. s=row['iso3166_2'],
  32. xy=row['centroid'].coords[0],
  33. horizontalalignment='center',
  34. va='center',
  35. color="white"
  36. )
  37. # 添加颜色
  38. sm = plt.cm.ScalarMappable(cmap='BuPu', norm=plt.Normalize(vmin=2, vmax=13))
  39. fig.colorbar(sm, orientation="horizontal", aspect=50, fraction=0.005, pad=0 );
  40. # 显示
  41. plt.show()

使用geopandas和matplotlib进行绘制,结果如下。

64605bad2c541648db0ae3f709702273.png

32. 变形地图

故名思义,就是形状发生改变的地图。

其中每个区域的形状,会根据数值发生扭曲变化。

这里没有相关的代码示例,直接上个图好了。

a8b57ff4e5b0cfa06ebcb665f89d25d9.png

33. 连接映射地图

连接地图可以显示地图上几个位置之间的连接关系。

航空上经常用到的飞线图,应该是这个的升级版。

  1. from mpl_toolkits.basemap import Basemap
  2. import matplotlib.pyplot as plt
  3. import pandas as pd
  4. # 数据
  5. cities = {
  6. 'city': ["Paris", "Melbourne", "Saint.Petersburg", "Abidjan", "Montreal", "Nairobi", "Salvador"],
  7. 'lon': [2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
  8. 'lat': [49, -38, 59.93, 5.33, 45.52, -1.29, -12.97]
  9. }
  10. df = pd.DataFrame(cities, columns=['city', 'lon', 'lat'])
  11. # 创建地图
  12. m = Basemap(llcrnrlon=-179, llcrnrlat=-60, urcrnrlon=179, urcrnrlat=70, projection='merc')
  13. m.drawmapboundary(fill_color='white', linewidth=0)
  14. m.fillcontinents(color='#f2f2f2', alpha=0.7)
  15. m.drawcoastlines(linewidth=0.1, color="white")
  16. # 循环建立连接
  17. for startIndex, startRow in df.iterrows():
  18. for endIndex in range(startIndex, len(df.index)):
  19. endRow = df.iloc[endIndex]
  20. m.drawgreatcircle(startRow.lon, startRow.lat, endRow.lon, endRow.lat, linewidth=1, color='#69b3a2');
  21. # 添加城市名称
  22. for i, row in df.iterrows():
  23. plt.annotate(row.city, xy=m(row.lon + 3, row.lat), verticalalignment='center')
  24. plt.show()

使用basemap绘制,结果如下。

cd0785a56f6531e08b7b7b4a17a8f763.png

34. 气泡地图

气泡地图,使用不同尺寸的圆来表示该地理坐标的数值。

  1. import folium
  2. import pandas as pd
  3. # 创建地图对象
  4. m = folium.Map(location=[20,0], tiles="OpenStreetMap", zoom_start=2)
  5. # 坐标点数据
  6. data = pd.DataFrame({
  7. 'lon': [-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5],
  8. 'lat': [-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97],
  9. 'name': ['Buenos Aires', 'Paris', 'melbourne', 'St Petersbourg', 'Abidjan', 'Montreal', 'Nairobi', 'Salvador'],
  10. 'value': [10, 12, 40, 70, 23, 43, 100, 43]
  11. }, dtype=str)
  12. # 添加气泡
  13. for i in range(0, len(data)):
  14. folium.Circle(
  15. location=[data.iloc[i]['lat'], data.iloc[i]['lon']],
  16. popup=data.iloc[i]['name'],
  17. radius=float(data.iloc[i]['value'])*20000,
  18. color='crimson',
  19. fill=True,
  20. fill_color='crimson'
  21. ).add_to(m)
  22. # 保存
  23. m.save('bubble-map.html')

使用Folium的Circle()进行绘制,结果如下。

80a8a02fb63c51ff796159fd3c41f96b.png

35. 和弦图

和弦图表示若干个实体(节点)之间的流或连接。

每个实体(节点)有圆形布局外部的一个片段表示。

然后在每个实体之间绘制弧线,弧线的大小与流的关系成正比。

  1. from chord import Chord
  2. matrix = [
  3. [0, 5, 6, 4, 7, 4],
  4. [5, 0, 5, 4, 6, 5],
  5. [6, 5, 0, 4, 5, 5],
  6. [4, 4, 4, 0, 5, 5],
  7. [7, 6, 5, 5, 0, 4],
  8. [4, 5, 5, 5, 4, 0],
  9. ]
  10. names = ["Action", "Adventure", "Comedy", "Drama", "Fantasy", "Thriller"]
  11. # 保存
  12. Chord(matrix, names).to_html("chord-diagram.html")

使用Chord库进行绘制,结果如下。

f0c55a21e9a611d7d8c3f40255340e9d.png

36. 网状图

网状图显示的是一组实体之间的连接关系。

每个实体由一个节点表示,节点之间通过线段连接。

  1. import pandas as pd
  2. import numpy as np
  3. import networkx as nx
  4. import matplotlib.pyplot as plt
  5. # 创建数据
  6. ind1 = [5, 10, 3, 4, 8, 10, 12, 1, 9, 4]
  7. ind5 = [1, 1, 13, 4, 18, 5, 2, 11, 3, 8]
  8. df = pd.DataFrame(
  9. {'A': ind1, 'B': ind1 + np.random.randint(10, size=(10)), 'C': ind1 + np.random.randint(10, size=(10)),
  10. 'D': ind1 + np.random.randint(5, size=(10)), 'E': ind1 + np.random.randint(5, size=(10)), 'F': ind5,
  11. 'G': ind5 + np.random.randint(5, size=(10)), 'H': ind5 + np.random.randint(5, size=(10)),
  12. 'I': ind5 + np.random.randint(5, size=(10)), 'J': ind5 + np.random.randint(5, size=(10))})
  13. # 计算相关性
  14. corr = df.corr()
  15. # 转换
  16. links = corr.stack().reset_index()
  17. links.columns = ['var1', 'var2', 'value']
  18. # 保持相关性超过一个阈值, 删除自相关性
  19. links_filtered = links.loc[(links['value'] > 0.8) & (links['var1'] != links['var2'])]
  20. # 生成图
  21. G = nx.from_pandas_edgelist(links_filtered, 'var1', 'var2')
  22. # 绘制网络
  23. nx.draw(G, with_labels=True, node_color='orange', node_size=400, edge_color='black', linewidths=1, font_size=15)
  24. # 显示
  25. plt.show()

使用NetworkX库进行绘制,结果如下。

7ac1c3ac237eb08e6a7bc29c2c74f869.png

37. 桑基图

桑基图是一种特殊的流图。

它主要用来表示原材料、能量等如何从初始形式经过中间过程的加工、转化到达最终形式。

Plotly可能是创建桑基图的最佳工具,通过Sankey()在几行代码中获得一个图表。

  1. import plotly.graph_objects as go
  2. import json
  3. # 读取数据
  4. with open('sankey_energy.json') as f:
  5. data = json.load(f)
  6. # 透明度
  7. opacity = 0.4
  8. # 颜色
  9. data['data'][0]['node']['color'] = ['rgba(255,0,255, 0.8)' if color == "magenta" else color for color in data['data'][0]['node']['color']]
  10. data['data'][0]['link']['color'] = [data['data'][0]['node']['color'][src].replace("0.8", str(opacity))
  11. for src in data['data'][0]['link']['source']]
  12. fig = go.Figure(data=[go.Sankey(
  13. valueformat=".0f",
  14. valuesuffix="TWh",
  15. # 点
  16. node=dict(
  17. pad=15,
  18. thickness=15,
  19. line=dict(color = "black", width = 0.5),
  20. label=data['data'][0]['node']['label'],
  21. color=data['data'][0]['node']['color']
  22. ),
  23. # 线
  24. link=dict(
  25. source=data['data'][0]['link']['source'],
  26. target=data['data'][0]['link']['target'],
  27. value=data['data'][0]['link']['value'],
  28. label=data['data'][0]['link']['label'],
  29. color=data['data'][0]['link']['color']
  30. ))])
  31. 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>",
  32. font_size=10)
  33. # 保持
  34. fig.write_html("sankey-diagram.html")

使用Plotly库进行绘制,结果如下。

3bcb5101304ff2c7d8f1a4f5f627156c.png

38. 弧线图

弧线图是一种特殊的网络图。

由代表实体的节点和显示实体之间关系的弧线组成的。

在弧线图中,节点沿单个轴显示,节点间通过圆弧线进行连接。

目前还不知道如何通过Python来构建弧线图,不过可以使用R或者D3.js。

下面就来看一个通过js生成的弧线图。

667054e81dc5d726d2b0ac74d149dfe4.png

39. 环形布局关系图

可视化目标之间的关系,可以减少复杂网络下观察混乱。

和弧线图一样,也只能通R或者D3.js绘制。

D3.js绘制的示例如下。

5258afc91538bbec248743b9bfb65f47.png

40. 动态图表

动态图表本质上就是显示一系列静态图表。

可以描述目标从一种状态到另一种状态的变化。

  1. import imageio
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. # 读取数据
  5. data = pd.read_csv('gapminderData.csv')
  6. # 更改格式
  7. data['continent'] = pd.Categorical(data['continent'])
  8. # 分辨率
  9. dpi = 96
  10. filenames = []
  11. # 每年的数据
  12. for i in data.year.unique():
  13. # 关闭交互式绘图
  14. plt.ioff()
  15. # 初始化
  16. fig = plt.figure(figsize=(680 / dpi, 480 / dpi), dpi=dpi)
  17. # 筛选数据
  18. subsetData = data[data.year == i]
  19. # 生成散点气泡图
  20. plt.scatter(
  21. x=subsetData['lifeExp'],
  22. y=subsetData['gdpPercap'],
  23. s=subsetData['pop'] / 200000,
  24. c=subsetData['continent'].cat.codes,
  25. cmap="Accent", alpha=0.6, edgecolors="white", linewidth=2)
  26. # 添加相关信息
  27. plt.yscale('log')
  28. plt.xlabel("Life Expectancy")
  29. plt.ylabel("GDP per Capita")
  30. plt.title("Year: " + str(i))
  31. plt.ylim(0, 100000)
  32. plt.xlim(30, 90)
  33. # 保存
  34. filename = './images/' + str(i) + '.png'
  35. filenames.append(filename)
  36. plt.savefig(fname=filename, dpi=96)
  37. plt.gca()
  38. plt.close(fig)
  39. # 生成GIF动态图表
  40. with imageio.get_writer('result.gif', mode='I', fps=5) as writer:
  41. for filename in filenames:
  42. image = imageio.imread(filename)
  43. writer.append_data(image)

以一个动态散点气泡图为例,

先用matplotlib绘制图表图片,再通过imageio生成GIF,结果如下。

dba33ff683d107ce3158d54f5ef933c1.gif

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

其中使用到的可视化库,大部分通过pip install即可完成安装。

有兴趣的小伙伴,可以自行去实践学习一下!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/644208
推荐阅读
相关标签
  

闽ICP备14008679号