7000 字 23 张图,Pandas一键生成炫酷的动态交互式图表

3813e996ae771e2aaadefe132663c6d4.gif

作者 | 俊欣

来源 | 关于数据分析与可视化

今天小编来演示一下如何用pandas一行代码来绘制可以动态交互的图表,并且将绘制的图表组合到一起,组成可视化大屏,本次小编将要绘制的图表有

  • 折线图

  • 散点图

  • 直方图

  • 柱状图

  • 饼图

  • 面积图

  • 地图

  • 组合图

准备工作

我们先导入需要用到的库,并做相应的设置

import pandas as pd
import pandas_bokeh
pandas_bokeh.output_notebook()

因为小编是在jupyter nobteook上面操作的,这边就用到了output_notebook()的设置

折线图

我们先来画一张简单的折线图,当中随机生成一批数据

import numpy as np

np.random.seed(55)
df = pd.DataFrame({"宁德时代": np.random.randn(100)+0.2, 
                   "贵州茅台": np.random.randn(100)+0.17}, 
                   index=pd.date_range('1/1/2021', periods=100))
df = df.cumsum()
df = df + 50
df.plot_bokeh(kind="line")

output

43d6ec3c6433ab203243b72d382a8006.gif

绘制出来的图表可以任意的缩放以及拖拽,我们也可以点击右边的“保存”按钮来实现对图表的下载保存,以至于图表的类型只需要对参数kind加以设定,我们将上面的代码优化一下

df.plot_bokeh.line(
    figsize=(800, 450),
    title="宁德时代 vs 贵州茅台",
    xlabel="日期",
    ylabel="股票价格 [$]",
    yticks=[0, 100, 200, 300, 400],
    ylim=(0, 100),
    xlim=("2021-01-01", "2021-04-01"),
    colormap=["red", "blue"],
    plot_data_points=True,
    plot_data_points_size=10,
    marker="asterisk")

output

fbe37831ede5e143843785db30f050ed.gif

我们对X轴以及Y轴坐标做了范围的限定,并且加上了标注,效果看起来也更加的美观一些。和pyecharts类似,我们也可以在图标的底部添加一个时间轴,拖动时间轴来展示数据

ts = pd.Series(np.random.randn(100), index=pd.date_range('1/1/2021', periods=100))
df = pd.DataFrame(np.random.randn(100, 4), index=ts.index, columns=list('ABCD'))
df = df.cumsum()

df.plot_bokeh(rangetool=True)

output

e02987ce99463c4d66ad9f6b2358e77d.gif

当然我们也可以对折线加以修改,就可以变成另外一种样子,主要修改的就是参数marker

x = np.arange(-5, 5, 0.1)
y2 = x**2
y3 = x**3
df = pd.DataFrame({"x": x, "Type 1": y2, "Type 2": y3})
df.plot_bokeh.point(
    x="x",
    xticks=range(-5, 5),
    size=5,
    colormap=["#009933", "#ff3399"],
    title="折线图 (Type 1 vs. Type 2)",
    marker="x")

output

bc6b314cce08ece22422adf3dba799f3.png

散点图

接下来我们来看散点图,步骤与上述的折线图相类似

df = pd.read_csv("iris.csv")
p_scatter = df.plot_bokeh.scatter(
    x="petal length(cm)",
    y="sepal width(cm)",
    category="species",
    title="Iris数据集可视化",
    show_figure=True,
)

output

ab3f2f2a480911e354d9af60de9db412.gif

我们在读取了iris数据集之后,将x参数和y参数上填上我们所要绘制的两列,而title参数则是设置图表的标题

我们也可以通过当中size这个参数来控制散点的大小,例如

df.loc[13, "sepal length(cm)"] = 15
df.loc[15, "sepal length(cm)"] = 17
df.loc[20, "sepal length(cm)"] = 30
df.loc[40, "sepal length(cm)"] = 20

p_scatter = df.plot_bokeh.scatter(
    x="petal length(cm)",
    y="sepal width(cm)",
    category="species",
    title="Iris数据集可视化",
    show_figure=True,
    size="sepal length(cm)"
)

output

d6f3412966be13e1aa60ad992fd5456b.gif

柱状图

下面我们来看一下直方图的绘制

data = {
    'fruits':
    ['苹果', '梨', '草莓', '西瓜', '葡萄', '香蕉'],
    '2015': [2, 1, 4, 3, 2, 4],
    '2016': [5, 3, 3, 2, 4, 6],
    '2017': [3, 2, 4, 4, 5, 3]
}
df = pd.DataFrame(data).set_index("fruits")

p_bar = df.plot_bokeh.bar(
    ylabel="每斤的的价格 [¥]", 
    title="水果每年的价格", 
    alpha=0.6)

output

d39714fc9fd3114f51d67cb0af235323.gif

我们看到上面的直方图是按照不同的年份分开来的,我们也可以堆叠起来,通过stacked这个参数来实现

p_stacked_bar = df.plot_bokeh.bar(
    ylabel="每斤的的价格 [¥]",
    title="水果每年的价格",
    stacked=True,
    alpha=0.6)

output

5befecd458ae7b2068d5c4b2c350b2ff.gif

直方图

绘制直方图的方式也是类似的

p_hist = df_hist.plot_bokeh.hist(
    y=["a", "b"],
    bins=np.arange(-5, 5, 0.5),
    normed=100,
    vertical_xlabel=True,
    ylabel="Share[%]",
    title="正则分布直方图",
    show_average=True,
    xlim=(-4, 6),
    ylim=(0, 30),
    show_figure=True)

output

96dad41a077ee1486c643c0275f9a674.png

小编个人觉得直方图有点丑,不知道大家是不是有类似的体验

面积图
df.plot_bokeh.area(
    x="Year",
    stacked=True,
    legend="top_left",
    colormap=["yellow", "orange", "black", "grey", "blue", "green"],
    title="全球不同能源的消耗量",
    ylabel="不同能源的消耗(吨)",
    ylim=(0, 16000))

output

e31cb369bae67c5234e30d0d08dc151f.gif

我们看到石油的消耗量一直都在不断的提升,另外有一个normed参数来帮助我们更好的观察数据的走势

df.plot_bokeh.area(
    x="Year",
    stacked=True,
    normed = 100,
    legend="bottom_left",
    colormap=["yellow", "orange", "black", "grey", "blue", "green"],
    title="全球不同能源的消耗量",
    ylabel="不同能源的消耗(吨)")

output

cccb4dffebc69469dacd44c125e56705.gif

饼图
df_pie.plot_bokeh.pie(
    x="Type",
    y="2017",
    colormap=["blue", "red", "yellow", "green", "purple", "orange", "grey"],
    title="饼图",
    )

output

3910d717f8444e1d717bf3a5852ee2e0.gif

上面的代码只是引用了表格当中的一列,当然我们也可以不做指定,引用表格当中的每一列数据

df_pie.plot_bokeh.pie(
    x="Type",
    colormap=["blue", "red", "yellow", "green", "purple", "orange", "grey"],
    title="多重饼图",
    line_color="black")

output

cdd62a43072cab6af41fab6befcee27f.gif

地图

同时我们来看一下地图的绘制,下面的图表是基于全球各大城市的人口密度分布来绘制的

df_mapped.plot_bokeh.map(
    x="longitude",
    y="latitude",
    hovertool_string="""<h2> @{name} </h2> 
    
                        <h3> Population: @{pop_max} </h3>""",
    tile_provider="STAMEN_TERRAIN_RETINA",
    size="population", 
    figsize=(900, 600),
    title="全球特大城市分布")

output

06fcccb1215b18a465b0f3288ff566b0.gif

从图中可以看出,亚洲的日本主要是集中在东京这块,而像在国内的话,有大家熟知的北上广深。上面的代码有两个参数xy分别对应的是经纬度,

import geopandas as gpd
import pandas_bokeh
pandas_bokeh.output_file("Interactive Plot.html")

df_states = gpd.read_file("states.geojson")
print(df_states.head())

下面这张图是美国各个州2017年的的人口总量,我们给上面的每一个州配上不同的颜色

df_states.plot_bokeh(
    figsize=(900, 600),
    category="POPESTIMATE2017",
    simplify_shapes=5000,
    colormap="Inferno",
    colormap_uselog=True,
    colorbar_tick_format="0.0a")

output

9020e512bff25ddbad6542cf4acd3974.gif

当然我们也可以在地图上面添加一个时间轴,让图表随着时间的流逝而变化

for i in range(8):
    df_states["Delta_Population_201%d"%i] = ((df_states["POPESTIMATE201%d"%i] / df_states["POPESTIMATE2010"]) -1 ) * 100
    
slider_columns = ["Delta_Population_201%d"%i for i in range(8)]
slider_range = range(2010, 2018)
df_states.plot_bokeh(
    figsize=(900, 600),
    simplify_shapes=5000,
    slider=slider_columns,
    slider_range=slider_range,
    slider_name="Year",
    colormap="Inferno",
    hovertool_columns=["STATE_NAME"] + slider_columns,
    title="Change of Population [%]")

output

98f3f36b57e8f6f2234589a3c5ca2b82.gif

同时我们也可以在地图上面添加一个下拉框,通过点选来筛选数据的展示

df_states["STATE_NAME_SMALL"] = df_states["STATE_NAME"].str.lower()

df_states.plot_bokeh(
    figsize=(900, 600),
    simplify_shapes=5000,
    dropdown=["POPESTIMATE2010", "POPESTIMATE2017"],
    colormap="Viridis",
    hovertool_string="""
                        <img
                        src="https://www.states101.com/img/flags/gif/small/@STATE_NAME_SMALL.gif" 
                        height="42" alt="@imgs" width="42"
                        style="float: left; margin: 0px 15px 15px 0px;"
                        border="2"></img>
                
                        <h2>  @STATE_NAME </h2>
                        <h3> 2010: @POPESTIMATE2010 </h3>
                        <h3> 2017: @POPESTIMATE2017 </h3>""",
    tile_provider_url=r"http://c.tile.stamen.com/watercolor/{Z}/{X}/{Y}.jpg",
    tile_attribution='Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
    )

output

d51dba11b1b7477fa171cf638a110baf.gif

最后我们可以通过区域的筛选来进行数据的呈现,通过`category`这个参数来实现

df_states.plot_bokeh(
    figsize=(900, 600),
    simplify_shapes=5000,
    category="REGION",
    show_colorbar=False,
    colormap=["blue", "yellow", "green", "red"],
    hovertool_columns=["STATE_NAME", "REGION"],
    tile_provider="STAMEN_TERRAIN_RETINA")

2763bcb301abefaacde5214b6aa77bab.gif

多图组合

pandas_bokeh模块也能够实现多张图表的组合,例如上面 人口密度的图表就可以和美国各大洲的人口总量的图表进行组合

#绘制出大致的轮廓图
figure = df_states.plot_bokeh(
    figsize=(800, 450),
    simplify_shapes=10000,
    show_figure=False,
    xlim=[-170, -80],
    ylim=[10, 70],
    category="REGION",
    colormap="Dark2",
    legend="States",
    show_colorbar=False,
)

#绘制人口的密度图
df_cities.plot_bokeh(
    figure=figure,         # <== pass figure here!
    category="pop_max",
    colormap="Viridis",
    colormap_uselog=True,
    size="size",
    hovertool_string="""<h1>@name</h1>
                        <h3>Population: @pop_max </h3>""",
    marker="inverted_triangle",
    legend="Cities",
)

3035a1ee30ae2455f3d35ef07dc71b2c.gif

上面的代码我们主要是用到了pandas_bokeh.plot_grid这个方法来将多个图结合起来,再来看几个简单的案例

df = pd.read_csv("iris.csv")

from bokeh.models.widgets import DataTable, TableColumn
from bokeh.models import ColumnDataSource

data_table = DataTable(
    columns=[TableColumn(field=Ci, title=Ci) for Ci in df.columns],
    source=ColumnDataSource(df),
    height=300,
)

# 创建散点图:
p_scatter = df.plot_bokeh.scatter(
    x="petal length(cm)",
    y="sepal width(cm)",
    category="species",
    title="Iris数据可视化",
    show_figure=False,
)

# Combine Table and Scatterplot via grid layout:
pandas_bokeh.plot_grid([[data_table, p_scatter]], plot_width=400, plot_height=350)

output

527352f97c5e399a2207c9e47fdb2e44.png

我们也可以借此多绘制几个直方图,然后组合起来

#重置表格的行索引:
df.reset_index(inplace=True)

#创建水平方向的直方图:
p_hbar = df.plot_bokeh(
    kind="barh",
    x="fruits",
    xlabel="Price per Unit [€]",
    title="Fruit prices per Year",
    alpha=0.6,
    legend = "bottom_right",
    show_figure=False)

#创建堆叠式的柱状图:
p_stacked_hbar = df.plot_bokeh.barh(
    x="fruits",
    stacked=True,
    xlabel="Price per Unit [€]",
    title="Fruit prices per Year",
    alpha=0.6,
    legend = "bottom_right",
    show_figure=False)

#Plot all barplot examples in a grid:
pandas_bokeh.plot_grid([[p_bar, p_stacked_bar],
                        [p_hbar, p_stacked_hbar]], 
                       plot_width=450)

output

98bcbcb8831476ab2c3ef0da92ab7453.png

69ae9f6b4d2fd474a7d09ade8c0a3b03.gif

5c4032d7f316e4acc4b9b3e8a266d714.png

资讯

GPT-3与小学生的做题之战……

资讯

人工智能又将如何破局?文末赠书

资讯

老龄化的Facebook能否再换新颜

福利

赠书|深度学习视频理解之图像分类

16ff4cf7f8545901c61e2d709acf18e0.png

分享

c1c2c2be0bc98ed6bcf2df07f33fd84d.png

点收藏

c48bbfec3e0b17194be3e57ab15130c5.png

点点赞

5fab34d70758889c17bbeac400663c34.png

点在看

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值