可视化神器plotly(1):基础图表与画布、坐标轴

删除回忆录丶 提交于 2020-12-20 23:07:55

楔子

<font size=4>下面来看一下plotly这个绘图神器,废话不多说,直接正题走起。</font>

图表绘制

import plotly as py
import plotly.graph_objs as go
import numpy as np
import pandas as pd

<font size=4>上面几个模块基本上先导入就行,plotly.graph_objs是专门用来绘制图表的,比如go.Scatter就是散点图,在plotly中,绘制出来的图表称之为一个trace(轨迹),然后轨迹显示在figure(画布)上面,当然一个画布是可以显示多个轨迹的。我们下面的代码在jupyter notebook上运行,可以直接显示图表。至于图表如何保存成图片,我们后面说。</font>

散点图

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100)
random_y2 = np.random.randn(100) - 5

# 里面的参数我们后面会一个一个解释
# 先看一部分
trace0 = go.Scatter(
    x=random_x,  # x轴的坐标
    y=random_y0,  # y轴的坐标
    mode="markers",  # 纯散点绘图
    name="markers"  # 曲线名称
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
    mode="markers + lines",  # 散点+线段绘图
    name="markers + lines" 
)

trace2 = go.Scatter(
    x=random_x,  
    y=random_y2, 
    mode="lines",  # 线段绘图
    name="lines"  
)  # 我们看到比较神奇的地方,Scatter居然也可以绘制线段。是的,如果不指定mode为markers,默认绘制的就是线段

# 我们的轨迹有了,下面干什么呢?对,创建画布
# 将轨迹组合成列表传进去,因为我们说一张画布是可以显示多条轨迹的
fig = go.Figure(data=[trace0, trace1, trace2])
# 在notebook,直接通过fig即可显示图表
fig

<font size=4>此时画布上的图表就已经显示出来了,可以看到比matplotlib漂亮多了。此时我们使用了4个参数,回顾一下:</font>

  • x:很好理解,就是x轴的坐标
  • y:很好理解,就是y轴的坐标
  • name:轨迹(图表)的名称,就是显示在画布右上方的那个
  • mode:轨迹的样式,markers就是纯散点,markers+lines是散点加上线段,lines是线段

<font size=4>我们再来看一个参数,marker:</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
    mode="markers",  
    name="上方",  
    marker={
        "size": 8,  # 点的大小
        # 点的颜色,三原色加上透明度,以字符串形式
        "color": "rgba(102, 198, 147, 0.7)",  
    }
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
    mode="markers",  
    name="下方",  
    marker={
        "size": 8,  
        "color": "rgba(252, 108, 117, 1)",  
        # 除此之外,还可以设置点的轮廓
        "line": {
            "width": 10,  # 线条大小
            "color": "rgba(1, 170, 118, 0.3)"  # 线条的颜色
        }
    }
)

fig = go.Figure(data=[trace0, trace1])
fig

<font size=4>现在我们有接触到了一个参数marker,这个是给点设置样式的。结构如下:</font>

marker = {
    # 点的大小
	"size": n,
    # 颜色,可以是rgba,也可以是rgb,也可以是颜色的英文名,比如green,yellow
    # 以及,它还可以是一个与对应轨迹的点的个数相同的数组,点对应的数组中不同的值、标记不同的颜色
    # 如果你知道机器学习里面的聚类的话,那么就当我在废话。
	"color": "rgba(n1, n2, n3, n4)",
    # 点的线条、轮廓
	"line": {"width": n, "color": "rgba(n1, n2, n3, n4)"}
	"showscale": True  # 其实还有一个showscale,默认为False,如果为True,那么会在右侧显示一个颜色条,可以自己去试一下
}

<font size=4>至于其它参数可以自己去查看,这里就不说了,只会说一些常用的,其它参数可能后面会涉及。但没涉及的话,可以通过help(go.Scatter)查看。不过可能有人会好奇,那如果我想添加标题以及坐标轴名称该怎么办?显然是可以添加的,只不过不在轨迹里面添加,而是在画布里面添加。</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
    mode="markers",  
    name="上方",  
    marker={
        "size": 8,  # 点的大小
        "color": "rgba(102, 198, 147, 0.7)",  # 点的颜色
    }
)

# 通过参数layout指定,其实应该是layout=go.Layout(title="这是标题"......)
# 但我们直接传入一个字典也是可以的
fig = go.Figure(data=[trace0], layout={"title": "这是标题", 
                                       "xaxis_title": "这是x轴",
                                       "yaxis_title": "这是y轴",
                                       # x轴坐标倾斜60度
                                       "xaxis": {"tickangle": 60}
                                      })
fig

<font size=4>我们看到通过向画布传入layout即可给画布设置一些额外属性,如下:</font>

  • title:标题
  • xaxis_title:x轴标题
  • yaxis_title:y轴标题
  • xaxis:坐标轴属性,可以传入一个字典。比如:tickangle就是将坐标倾斜,尤其是日期比较长,那么我们就可以通过倾斜方式来避免堆叠在一起。角度大于0顺时针,小于0逆时针。同理还有yaxis,当然这个字典里面还可以指定其它属性,但是我们不一定都要用到,而是会用到什么写什么,因为它们内部支持的属性不仅仅只针对一种图表。

<font size=4>当然除了上面这些,我们再说几个常用的:</font>

  • width:画布的宽度
  • height:画布的高度
  • template:画布风格,有以下几种选择:ggplot2,seaborn,simple_white,plotly,plotly_white,plotly_dark,presentation,xgridoff,ygridoff,gridon,none。默认是plotly
random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
    mode="markers",  
    name="上方",  
    marker={
        "size": 8,  # 点的大小
        "color": "rgba(102, 198, 147, 0.7)",  # 点的颜色
    }
)

fig = go.Figure(data=[trace0], layout={"template": "plotly_dark"})
fig

<font size=4>layout还支持其它哪些参数,可以通过help(go.Layout)查看,当然我们后面可能也会介绍几个。</font>

线形图

<font size=4>线形图,或者折线图,它也是通过Scatter来绘制的。</font>

# sick是数据集,这个不需要关心,你完全可以使用其他的数据集代替
trace0 = go.Scatter(
    x=sick["date"],  
    y=sick["number"], 
)

fig = go.Figure(data=[trace0], layout={"template": "plotly_dark",
                                       "title": "当前的患者人数"})
fig

<font size=4>虽然名叫Scatter,但是默认绘制的是折线图,还记得怎么绘制散点图吗?对的,指定mode="markers"即可。</font>

<font size=4>如果我想给折线添加样式肿么办?我们给散点图添加样式通过参数marker指定,而给折线添加样式也有对应的参数。</font>

sick = df.loc[(df["country"] == "China")&(df["status"] == "confirmed"), ["date", "number"]].groupby(by=["date"], as_index=False).sum().sort_values(by="date")

trace0 = go.Scatter(
    x=sick["date"],  
    y=sick["number"],
    line={
        "width": 3,  # 折线的宽度
        "color": "rgba(255, 30, 186, 1)"  # 折线的颜色
    }
)

fig = go.Figure(data=[trace0], layout={"template": "plotly_dark",
                                       "title": "当前的患者人数"})
fig

<font size=4>我们看到此时折线的样式就改变了,但是我们记得之前在设置散点图的时候好像也用到了line,没错。只不过那个line是传给marker参数的字典里面的一个key,用来设置点的线条、或者轮廓的样式的,而这里的line它是一个参数,和marker参数是同级别的,是用来设置折线的样式的。</font>

<font size=4>参数line里面还可以指定折线的种类,是虚线、实线等等之类的。</font>

trace0 = go.Scatter(
    x=sick["date"],  
    y=sick["number"],
    line={
        "width": 3,  
        "color": "rgba(255, 30, 186, 1)",  
        "dash": "dot"  # 指定为虚线
    }
)

fig = go.Figure(data=[trace0], layout={"template": "plotly_dark",
                                       "title": "当前的患者人数"})
fig

<font size=4>"dash"表示指定线条的种类:</font>

  • dot:由点组成的虚线
  • dash:由短线组成的虚线
  • dashdot:由点和短线组成的虚线

<font size=4>有时候,我们的数据并不是连续的,中间可能会出现断层,这个时候我们可以指定connectgaps参数,举个栗子</font>

x = np.array([1, 2, np.nan, 4, 5]) 
y1 = x * 3 + 1
y2 = x * 3 + 2

trace0 = go.Scatter(
    x=x,  
    y=y1,
)

trace1 = go.Scatter(
    x=x,
    y=y2,
    connectgaps=True
)

fig = go.Figure(data=[trace0, trace1])
fig

<font size=4>当数据出现了空值的时候,那么折线默认是会出现断层的,而指定connectgaps=True,那么会将缺失值两端的点直接相连,使得直线是完整的。</font>

柱状图

<font size=4>最简单的柱状图如下:</font>

trace0 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[17, 400, 16, 17],
)


fig = go.Figure(data=[trace0])
fig

<font size=4>这个图形看起来就很漂亮,再次踩一脚matplotlib。当然我们可以绘制多个柱状图:</font>

trace0 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[17, 400, 16, 17],
    name="bar1"
)

trace1 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[86, 90, 96, 87],
    name="bar2"
)

fig = go.Figure(data=[trace0, trace1])
fig

<font size=4>除此之外我们还可以指定层叠柱状图:</font>

trace0 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[17, 400, 16, 17],
    name="bar1"
)

trace1 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[86, 90, 96, 87],
    name="bar2"
)

# 指定layout里面的barmode为stack,会将柱状图堆叠在一起
# 我们看到又多了一个barmode,所以我们说可调节的属性非常多,但是不同的属性适用于不同的轨迹,我们需要哪个就设置哪个即可。
fig = go.Figure(data=[trace0, trace1], layout={"barmode": "stack"})
fig

<font size=4>我们看到层叠柱状图是在画布里面设置的,因为将两个轨迹怎么组合是通过画布来设置的,至于Bar里面的参数是设置轨迹本身, 比如我们还可以调节颜色什么的,通过参数marker指定:</font>

trace0 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[17, 400, 16, 17],
    name="bar1",
    marker={
        # 除了rgba,还可以通过颜色的名称指定
        "color": "pink",
        "opacity": 1,  # 指定透明度,当然这里指定透明度的方式,同样适用于Scatter
        "line": {
            "width": 3,  # 轮廓的宽度
            "color": "cyan",  # 轮廓的颜色
        },
    }
)

trace1 = go.Bar(
    x=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    y=[86, 90, 96, 87],
    name="bar2",
    marker={
        "color": "green"
    }
)

fig = go.Figure(data=[trace0, trace1], layout={"template": "plotly_dark"})
fig

<font size=4>我们看到轨迹的颜色什么的也是通过marker指定的,里面也可以设置轮廓,和Scatter是类似的。</font>

<font size=4>至于支持的一些其它参数,可以通过help(go.Bar)查看。</font>

水平柱状图

<font size=4>水平柱状图和柱状图类似,也是通过go.Bar来绘制,只不过需要多加一个参数。</font>

trace0 = go.Bar(
    # 方向变了,所以x轴和y轴的数据也要调换位置
    y=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    x=[17, 400, 16, 17],
    name="bar1",
    marker={
        "color": "pink",
    },
    # 指定为水平方向即可
    orientation="h"
)

trace1 = go.Bar(
    y=["古明地觉", "芙兰朵露", "古明地恋", "椎名真白"],  
    x=[86, 90, 96, 87],
    name="bar2",
    marker={
        "color": "green"
    },
    orientation="h"
)

fig = go.Figure(data=[trace0, trace1], layout={"template": "plotly_dark"})
fig

<font size=4>柱状图有多高取决于y轴,而水平柱状图有多长就取决于x轴了,所以此时x轴就是代表数值的那一方。至于设置颜色、轮廓等参数,和之前的柱状图一样。</font>

甘特图

<font size=4>甘特图又称横道图,是用来显示项目进度等与时间相关的数据的。直接看个栗子就很好理解了:</font>

# 创建甘特图,使用plotly.figure_factory,然后调用内部的create_gantt即可
import plotly.figure_factory as ff

tasks = [
    {"Task": "任务A", "Start": "2018-1-1", "Finish": "2018-3-1"},
    {"Task": "任务B", "Start": "2018-2-1", "Finish": "2018-5-1"},
    {"Task": "任务C", "Start": "2018-2-1", "Finish": "2018-6-1"},
    {"Task": "任务D", "Start": "2018-4-1", "Finish": "2018-8-1"},
    {"Task": "任务E", "Start": "2018-8-1", "Finish": "2019-1-1"}
]
# 但是数据格式有要求,里面是一个列表,列表里面是字典
# 字典包含至少三个键值对,分别是Task:任务,Start:开始时间,Finish:结束时间,不能是其它的名字
fig = ff.create_gantt(tasks, title="这是甘特图")
# 当然此时调整画布属性的参数就不能通过layout={}指定了,而是直接在里面传递
# 因为它创建轨迹的时候,直接就把画布顺便给你创建了,所以返回的就是一个画布,我们可以直接显示
fig

<font size=4>里面也可以直接传递一个DataFrame</font>

import plotly.figure_factory as ff
# 除了Task、Start、Finish,之外还可以有一个Complete,来表示任务完成的进度。
# 0表示无进展,100表示全部完成
df = pd.DataFrame({"Task": ["任务A", "任务B", "任务C", "任务D","任务E"],
                   "Start": ["2018-1-1", "2018-2-1", "2018-2-1", "2018-4-1", "2018-8-1"],
                   "Finish": ["2018-3-1", "2018-5-1", "2018-6-1", "2018-8-1", "2019-1-1"],
                   "Complete": [10, 80, 80, 76, 100]
                  })

# 但是有了进度还不行,我们需要设置index_col="Complete",这样进度相同的条就会显示一样的颜色
# 并且我们还可以通过show_colorbar=True,来将颜色进行标记,到底哪种颜色对应的进度高、哪种对应的进度低
fig = ff.create_gantt(df, index_col="Complete", show_colorbar=True)
# 另外虽说自动帮我们创建了画布,但我们还是希望自己指定画布。所以我们就需要将自动创建的画布上面的轨迹放在我们自己创建的画布上
traces = fig.data  # 这里就拿到了画布上的轨迹,因为画布上可以有多条轨迹,所以得到的是一个元组
# 我们直接根据traces创建即可,data接收列表或者元组都是一样的
fig = go.Figure(data=traces, 
                layout={"template": "plotly_dark", 
                        "title": "这是我们自己创建的画布上面的甘特图"})  # 此时就可以像之前一样指定属性了
fig

<font size=4>我们看到Complete对应值相同的任务,颜色是一致的。并且右侧的条表示颜色对应的任务进度,这是通过show_colorbar=True显示的。并且此时的数据我们用到了四个参数:Task、Start、Finish、Complete,前三个是固定的必须叫这几个名字,至于Complete就没有要求了,叫其他的名字也是可以的,但是最好要见名知意,然后设置为index_col,指定show_colorbar=True。</font>

<font size=4>并且我们除了通过数值来表示进度,还可以使用文字。</font>

df = pd.DataFrame({"Task": ["任务A", "任务B", "任务C", "任务D","任务E"],
                   "Start": ["2018-1-1", "2018-2-1", "2018-2-1", "2018-4-1", "2018-8-1"],
                   "Finish": ["2018-3-1", "2018-5-1", "2018-6-1", "2018-8-1", "2019-1-1"],
                   "Complete": ["干了一小半", "干了一半", "干了一半", "干了一大半", "全干完了"]
                  })

# 为不同的进度赋予不同的颜色,通过rgb指定
colors = {
    "干了一小半": "rgb(125, 135, 144)",
    "干了一半": "rgb(187, 20, 168)",
    "干了一大半": "rgb(14, 199, 250)",
    "全干完了": "rgb(250, 1, 144)"
}

fig = ff.create_gantt(df, index_col="Complete", show_colorbar=True, colors=colors)  # 通过colors参数指定颜色,如果不指定会默认会为不同的进度附上不同的颜色
traces = fig.data 
fig = go.Figure(data=traces, 
                layout={"template": "plotly_dark", 
                        "title": "这是我们自己创建的画布上面的甘特图"})  
fig

面积图

<font size=4>绘制面积图依旧使用Scatter,所以Scatter可以用来绘制三种图形了。我们说里面参数非常多,因为它可以针对不同的图表。所以这些参数没必要在刚学的Scatter的时候一下子全部掌握,再加上它可以用在不同的地方,因此一下子学习全部参数比较累。所以,最好的建议是,针对图表或者轨迹来使用,当前绘制的轨迹需要哪些参数就学习哪些参数、或者使用哪些参数即可。</font>

<font size=4>绘制面积图关键在于里面的一个fill参数</font>

x = np.linspace(0, 2, 100)
y0 = np.cos(x)
y1 = np.sin(x)

trace0 = go.Scatter(
    x=x,
    y=y0,
    name="cos",
    mode="markers",  # 我们说默认是折线,但是散点也是可以的
    fill="tozeroy"
)
trace1 = go.Scatter(
    x=x,
    y=y1,
    name="sin",
    mode="none",  # mode还可以设置为none,表示将线段隐藏
    fill="tozeroy"
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "面积", "template": "plotly_dark"})
fig

<font size=4>我们看到面积图就是将轨迹和x轴围成的部分涂上颜色,仔细观察橘色的sin,线段没了,因为围成的部分有颜色,所以线段或者此时的面积图的边界线就可以隐藏掉了。如果不指定fill,直接指定mode="none"也是可以隐藏的,只不过此时绘制的线段你就看不到了。另外,我们看到即使是散点也是可以围成面积图的,会用线将点拟合起来,再绘制围成的面积图。</font>

<font size=4>此时我们又看到了一个参数fill,这个fill就是用来绘制面积图的,当然在学习或者绘制散点图的时候,这个fill无需鸟它。我们将fill指定为"tozeroy"表示绘制和x轴围城的部分,很好理解,"tozeroy"不是就是"to"(到)"zeroy"(y为0的地方)嘛,所以是x轴。当然除了,"tozeroy",还可以为"none",表示不围成面积,当然此时直接不指定fill就行了。除了这些,还可以指定为其它的一些值:</font>

  • none:不绘制面积
  • tozeroy:与x轴围成的面积
  • tozerox:与y轴围成的面积
  • toself:与自身围成的面积。
x = np.linspace(0, 2, 100)
y0 = np.cos(x)
y1 = np.sin(x)

trace0 = go.Scatter(
    x=x,
    y=y0,
    name="cos",
    mode="none",  
    fill="tozerox"  # 和y轴围成的面积
)
trace1 = go.Scatter(
    x=x,
    y=y1,
    name="sin",
    mode="none",  
    fill="toself"  # 和自身围成的面积
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "面积", "template": "plotly_dark"})
fig

  • tonext:和下一条线围成的面积
  • tonexty:和下一条线在x轴上围成的面积
  • tonextx:和下一条线在y轴上围成的面积

<font size=4>上面三个属性则是专门用来绘制两条线围成的面积,只需要第一条轨迹不填充,第二条轨迹填充即可。</font>

x = np.linspace(0, 2, 100)
y0 = np.cos(x)
y1 = np.sin(x)

trace0 = go.Scatter(
    x=x,
    y=y0,
    name="cos"  # 不指定fill,也就是不填充
)
trace1 = go.Scatter(
    x=x,
    y=y1,
    name="sin",
    mode="none",
    fill="tonexty"  # 和另一条轨迹y轴围成的面积
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "面积", "template": "plotly_dark"})
fig

<font size=4>我们变得到了两条线、或者轨迹在x轴上围成的面积图,同理tonextx和tonext可以自己绘制一下。但是一般我们使用的是tonexty,即、绘制两条线在x轴围成的面积图</font>

<font size=4>除此之外,我们还可以绘制出堆叠面积图,当然方法还是类似的。</font>

x = np.array([1, 3, 2, 3, 5])
y0 = x + 1
y1 = x + 2
y2 = x + 3
y3 = x + 4

trace0 = go.Scatter(
    x=x,
    y=y0,
    name="y0",
    fill="tonexty"
)
trace1 = go.Scatter(
    x=x,
    y=y1,
    name="y1",
    fill="tonexty"
)
trace2 = go.Scatter(
    x=x,
    y=y2,
    name="y2",
    fill="tonexty"
)
trace3 = go.Scatter(
    x=x,
    y=y3,
    name="y3",
    fill="tonexty"
)
fig = go.Figure(data=[trace0, trace1, trace2, trace3], layout={"title": "面积", "template": "plotly_dark"})
fig

直方图

<font size=4>直方图种类比较多,我们分个小标题吧</font>

基本直方图

x = np.random.randint(1, 20, 1000)  # 生成100个1到20的随机数

trace0 = go.Histogram(
    x=x,
)

fig = go.Figure(data=[trace0], layout={"title": "直方图", 
                                       "template": "plotly_dark",
                                      })
fig

<font size=4>但是我们看到可读有些不完美,就是跨越的太大了,从0直接到5了,所以我们可以指定xaxis属性。</font>

x = np.random.randint(1, 20, 1000)  # 生成100个1到20的随机数

trace0 = go.Histogram(
    x=x,
    histnorm="probability"  # 指定histnorm为probability,那么y轴将不再显示数量而是显示比例
)

fig = go.Figure(data=[trace0], layout={"title": "直方图", 
                                       "template": "plotly_dark",
                                       "xaxis": {"dtick": 2, "range": [1, 20]}  # range表示坐标范围,dtick表示相邻坐标之间的差值,这里是1,所以就是 0 2 4 6...
                                      })
fig

<font size=4>我们看到y轴的数量变成了比例,当然最重要的就是我们知道了如何调整坐标范围与坐标刻度了,当然我们后面会对画布、坐标什么的做一个全面的总结,里面可以指定哪些属性、都具有哪些效果之类的,当然还是只会介绍我个人认为可能会用到的。如果没有你想要的,可以去官网查看,抱歉啦。</font>

重叠直方图

<font size=4>忘记说了,其实所有的图表对应的类里面,很多参数都是相同的,比如marker设置图表本身的颜色透明度、以及轮廓的颜色、大小,name设置图表的名称等等,这些参数我们不再赘述,而是会直接使用。</font>

x0 = np.random.randn(1000) 
x1 = np.random.chisquare(5, 1000)
trace0 = go.Histogram(
    x=x0,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
trace1 = go.Histogram(
    x=x1,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "直方图", 
                                               "template": "plotly_dark",
                                              })
fig

<font size=4>但是我们发现这个直方图貌似有些不对劲,因为plotly将多个直方图强制变窄了,我们需要将barmode指定为"overlay"</font>

x0 = np.random.randn(1000) 
x1 = np.random.chisquare(5, 1000)
trace0 = go.Histogram(
    x=x0,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
trace1 = go.Histogram(
    x=x1,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "直方图", 
                                               "template": "plotly_dark",
                                               "barmode": "overlay"
                                              })
fig

堆叠直方图

<font size=4>和柱状图类似,需要指定barmode为"stack"</font>

x0 = np.random.randn(1000) 
x1 = np.random.randn(1000)
trace0 = go.Histogram(
    x=x0,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
trace1 = go.Histogram(
    x=x1,
    histnorm="probability",
    marker={
        "opacity": 0.75
    }
)
fig = go.Figure(data=[trace0, trace1], layout={"title": "直方图", 
                                               "template": "plotly_dark",
                                               "barmode": "stack"
                                              })
fig

累计直方图

<font size=4>直方图的累计形式,第n+1个区间的样本数是第n-1个区间的样本数加上第n个区间的样本数。</font>

x0 = np.random.randn(1000) 
trace0 = go.Histogram(
    x=x0,
    histnorm="probability",
    marker={
        "opacity": 0.75
    },
    cumulative={"enabled": True}  # 指定cumulative即可
)

fig = go.Figure(data=[trace0], layout={"title": "直方图", 
                                               "template": "plotly_dark",
                                              })
fig

饼图

<font size=4>饼图就很简单了,使用Pie这个类,Scatter里面的x和y对应Pie里面labels和values</font>

trace0 = go.Pie(
    labels=["古明地觉", "芙兰朵露", "古明地恋", "雾雨魔理沙", "紫妈"],
    values=[10, 25, 5, 35, 41]
)

fig = go.Figure(data=[trace0], layout={"title": "饼图", 
                                        "template": "plotly_dark",
                                      })
fig

<font size=4>我们还可以设置环形饼图,就是在中间挖一个洞</font>

trace0 = go.Pie(
    labels=["古明地觉", "芙兰朵露", "古明地恋", "雾雨魔理沙", "紫妈"],
    values=[10, 25, 5, 35, 41],
    hole=0.7  # 从中心挖掉百分之70的部分
)

fig = go.Figure(data=[trace0], layout={"title": "饼图", 
                                        "template": "plotly_dark",
                                      })
fig

<font size=4>我们还可以将饼图旋转一定角度,我们看到最上方的两个部分明显是垂直分隔的,另外我们还可以使某一个部分突出。</font>

trace0 = go.Pie(
    labels=["古明地觉", "芙兰朵露", "古明地恋", "雾雨魔理沙", "紫妈"],
    values=[10, 25, 5, 35, 41],
    pull=[0, 0, 0, 0, 0.1],  # 突出最后一个
    rotation=30,  # 旋转30度
    # 饼图也有marker参数,其实基本上所有图表都有marker参数
    marker={
        # 显然color就是饼图的颜色了,但是它和散点图不一样
        # 散点图可以指定一种颜色来让所有的点都呈现相同的颜色,但是饼图的每一部分应该是不同的颜色,这才符合饼图这种图形的意义
        # 所以我们要传入一个列表,因为我们数据有五个,那么我们要指定五种颜色。但是即便不指定五个、或者颜色重复也是可以的。
        # 如果颜色不够,plotly会帮你补充,颜色多了,会只选列表的前五个
        "colors": ["yellow", "green", "cyan", "pink", "blue"],  # 并且这里不叫color了,而是叫colors,因为多个颜色
        "line": {
            "width": 3,
            "color": "white",  # 轮廓颜色,这里需要指定一种,整个饼图的轮廓的颜色是一样的
        }
    }
)

fig = go.Figure(data=[trace0], layout={"title": "饼图", 
                                        "template": "plotly_dark",
                                      })
fig

不是总结的总结

<font size=4>到目前为止,我们介绍了常用的几个图表。重点就是plotly里面的轨迹和画布两个概念,我们使用Scatter、Pie、Bar等等得到的都是轨迹,然后还需要创建画布,将轨迹写在画布上,然后显示画布即可。至于轨迹,不同的轨迹的参数不同,plotly最让人想批评的就是它的使用太复杂,其实也不算复杂。说白了就是参数太多了,但是功能强大也是没办法的事情。不过虽然如此,可不同的轨迹有很多参数都是类似的,首先两个坐标轴的数据就不用说了。其次就是name和marker,name是给轨迹起名字,如果画布上有多条轨迹能够让我们区分。还有就是marker,我们说marker结构如下:</font>

{
    "color或者colors": "表示轨迹本身的颜色",
    "opacity": "透明度",
    "line": {
        "width": "线条或者轮廓的宽度",
        "color": "线条或者轮廓的颜色"
    }
}
# 其中color的表现形式有很多,可以是颜色的英文名,比如:"yellow"
# 也可以是rgb三原色,比如:"rgb(255, 255, 255)"
# 还可以是rgba,比如:"rgba(255, 255, 255, 0.5)",相当于在rgb基础上加上了透明度
# rgba的好处就是,"line": {}里面是不支持"opacity"的,如果想设置轮廓的透明度,可以通过rgba设置颜色的同时指定透明度
# 但是对于marker={}里面是可以支持指定key为"opacity"来设置透明度的,当然通过rgba也可以

# 当然marker里面还可以指定其它的key,比如"size",这个是适用于散点图的,用来指定点的大小,但是对于饼图就不行
# 而"color或者colors"、"opacity"、"line"对于所有图形都是适用的

<font size=4>而我们说通过marker就可以绘制出漂亮的图形了,其实plotly的图表本身就很漂亮。至于轨迹的其它参数就就取决于轨迹本身的类型了,其实只要把绘制每个轨迹的关键参数记住,也就那么几个,再搭配marker,我们就能绘制出漂亮的图表的,因为plotly默认绘制的图表就很漂亮。</font>

<font size=4>至于像标题、坐标轴名称什么的,我们是通过画布来指定的。我们使用go.Figure来创建画布,我们实例化Figure这个类的时候,里面传递了两个参数,一个是data、一个是layout。data很好理解,就是多个轨迹组成的列表,一个轨迹也要放在列表里面传进去。而layout则就是我们关心的、设置画布的属性了,而layout我们目前是通过字典传递的。</font>

# 我们目前是这样传递layout的
fig = go.Figure(data=[trace0, ...], layout={"title": "xxx"})

# 其实layout,我们可以实例化一个类
layout = go.Layout(title="xxx")  # 等价于layout = {"title": "xxx"}
fig = go.Figure(data=[trace0, ...], layout=layout)

# 字典传递比较方便,所以我个人更倾向使用字典,但是具体使用哪种,看你个人。

<font size=4>而layout我们目前都设置了哪些属性呢?</font>

layout = {
    "title": "图表的标题",
    "xaxis_title": "x轴的名称",
    "yaxis_title": "y轴的名称",
    "template": "图表的风格,支持哪几种可以回头翻一翻,我个人非常喜欢plotly_dark",
    "xaxis": {"range": "坐标轴的范围", "dtick": "刻度大小", "tickangle": "坐标旋转角度"}  # xaxis里面支持的属性也非常多,后面我们会总结
    "yaxis": "和xaxis同理",
    "barmode": "设置柱状图和直方图的堆叠属性的"
}
# layout里面支持的属性也非常多,我们后面也会说。
# 但是有些属性并不是通用的,比如barmode,当绘制散点图的时候,它就不需要了
# 不过layout的特点就在于即使你传递了也不会报错,比如明明绘制的散点图,但是在画布上却指定了"barmode"
# 因为画布它是针对所有轨迹的,所以即使画布上有该轨迹不需要的参数也无影响。
# 然而如果是轨迹则不行了,比如在柱状图的marker={}里面指定了散点图才需要的"size"就会报错了,因为柱状图不需要"size"

<font size=4>尽管layout里面的可设置的属性比较多,但是有的是通用的,比如:title、xaxis_title、yaxis_title、template、xaxis、yaxis,但有些则是针对特定轨迹的,比如barmode。</font>

<font size=4>掌握上面这些,对于工作中差不多够用了。但是我们还是要介绍一些更高级的东西,比如时间序列、多图绘制等等,不过要在下一篇博客中说了。</font>

其它轨迹

<font size=4>都说了,上面不是总结了。我们再来说一下其它的轨迹(包含上面已经介绍的轨迹),至于长什么样子,可以自己尝试。这些都可以通过plotly.graph_objs进行调用,里面的参数可以通过help(go.xxx)查看</font>

2d平面轨迹

  • AngularAxis:极坐标图表
  • Area:区域图
  • Bar:柱状图
  • Barpolar:极坐标柱状图
  • Box:盒形图,又称箱型图
  • Candlestick和Ohlc:金融股票行业常用的k线图和OHLC曲线图
  • ColorBar:彩条图
  • Contour:轮廓图
  • Choropleth:等值线图
  • Line:曲线图
  • Heatmap:热点图
  • Histogram:直方图
  • Histogram2d:2d平面直方图
  • Histogram2dContour:2d轮廓直方图
  • Scatter:散点图、折线图

3d立体轨迹

  • Scatter3d:3d立体散点图、折线图
  • Surface:表面图
  • Mesh3d:3d立体网格图
  • Pointcloud:云点图

maps地图

  • Scattergeo:基于地图模式的散点图、折线图
  • Choropleth:立体等值线图
  • Scattermapbox:基于地图的散点图

<font size=4>当然plotly.graph_objs里面支持的轨迹还不止上面说的这些,有兴趣可以自己查看。</font>

layout

<font size=4>重点来了,我们说layout是给画布设置属性的,我们通过一个字典传递,那么通过字典都能传递哪些属性呢?下面来看一看,还是介绍我个人认为会使用的,有些参数会简单说明,有些参数我们以折线图举例说明。</font>

<font size=5 color="#FF118C">title:标题</font>

<font size=5 color="#FF118C">xaxis_title:x轴名称</font>

<font size=5 color="#FF118C">yaxis_title:y轴名称</font>

<font size=5 color="#FF118C">template:背景风格</font>

<font size=4>template:支持ggplot2,seaborn,simple_white,plotly,plotly_white,plotly_dark,presentation,xgridoff,ygridoff,gridon,none。默认是plotly</font>

<font size=5 color="#FF118C">titlefont:标题字体</font>

<font size=5 color="#FF118C">autosize:自动调整大小(不常用)</font>

<font size=5 color="#FF118C">bargap:柱状图间距</font>

<font size=5 color="#FF118C">bargroupgap:柱状图组间距,如果绘制多个柱状图的话</font>

<font size=5 color="#FF118C">barmode:柱状图或直方图模式</font>

<font size=5 color="#FF118C">boxgap:箱型图间距</font>

<font size=5 color="#FF118C">boxgroupgap:箱型图组间距</font>

<font size=5 color="#FF118C">boxmode:箱型图模式</font>

<font size=5 color="#FF118C">calendar:日历</font>

<font size=4>calendar:可以是以下字符串gregorian,chinese,coptic,discworld,ethiopian,hebrew,islamic,julian,mayan,nanakshahi,nepali,persian,jalali,taiwan,thai,ummalqura之一</font>

<font size=5 color="#FF118C">direction:方向</font>

<font size=4>可以是clockwise(顺时针)、counterclockwise(逆时针)之一</font>

<font size=5 color="#FF118C">dragmode:图形拽动模式</font>

<font size=4>可以是zoom,pan,select,lasso,orbit,turntable,False(布尔)之一</font>

<font size=5 color="#FF118C">font:字体</font>

<font size=4>传入一个字典:{"color": "颜色", "family": "字体类型", "size": "字体大小"},当然颜色、字体类型、大小不一定要全部指定</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)

fig = go.Figure(data=[trace0, trace1], layout={"font": {"color": "green", "size": 20, "family": "stcaiyun"}, 
                                        })
fig

<font size=4>我们看到字体的颜色、大小、类型都变了。</font>

<font size=5 color="#FF118C">geo:地理参数</font>

<font size=5 color="#FF118C">height:图表高度,默认450</font>

<font size=5 color="#FF118C">width:图表宽度,默认700</font>

<font size=5 color="#FF118C">legend:设置右上角那个东东的属性</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)

fig = go.Figure(data=[trace0, trace1], layout={"legend": {"bgcolor": "pink"}, 
                                        })
fig

<font size=4>我们看到变成了粉色。</font>

<font size=5 color="#FF118C">hovermode:鼠标指针悬停时显示的数据</font>

<font size=4>这个在jupyter notebook中使用,选项为: "x","y","closest",False之一</font>

<font size=5 color="#FF118C">margin:图表边缘间距</font>

<font size=5 color="#FF118C">orientation:方向,针对柱状图。默认是竖向,横向需要指定此参数为"h"</font>

<font size=5 color="#FF118C">paper_bgcolor:画布背景颜色</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={
    "paper_bgcolor": "yellow"
})
fig 

<font size=5 color="#FF118C">plot_bgcolor:图形背景颜色,坐标轴围成的区域</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)

fig = go.Figure(data=[trace0, trace1], layout={"plot_bgcolor": "#ACFFCF",  # 忘记说了,表示color还可以使用16进制的字符串
                                        })
fig

<font size=4>如果和template搭配使用会是什么效果?</font>

<font size=4>指定template为"plotly_dark"的时候会变成这样子,个人觉得不太行,你觉得呢?</font>

<font size=5 color="#FF118C">showlegend:默认为True,如果为False,那么右上角的那个东东就不显示了,就是我们在轨迹中指定的name</font>

<font size=5 color="#FF118C">images:我个人觉得最牛的一个功能,就是可以将图片作为背景。</font>

from PIL import Image
im = Image.open(r"C:\Users\satori\Desktop\bg\雾雨魔理沙.png")
random_x = np.linspace(0, 2, 100)  
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100)
random_y2 = np.random.randn(100) - 5
trace0 = go.Scatter(
    x=random_x, 
    y=random_y0,  
    mode="markers",  
    name="markers"  
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
    mode="markers + lines", 
    name="markers + lines" 
)

trace2 = go.Scatter(
    x=random_x,  
    y=random_y2, 
    mode="lines",  
    name="lines"  
)
fig = go.Figure(data=[trace0, trace1, trace2], 
               layout={
                   "images": [
                       {"source": im,  # 可以是PIL读取的Image对象,也可以是base64字符
                        "sizex": 1, 
                        "sizey": 1, 
                        "yanchor": "bottom", 
                        "opacity": 0.3,  # 其它的不要变,只变透明度即可
                        }
                   ],
                   # 这里需要一个width和height表示图表的宽和高,我们上面说了的
                   # 主要是为了和图片进行匹配,具体多少取决于你的图片,这个可以自己试一下
                   # 另外记得把legend也考虑在内
                   "width": im.width - 41,
                   "height": im.height,
                },
                
               )
fig

<font size=5 color="#FF118C">xaxis和yaxis:非常重要的属性,关键的东西我们留到最后。</font>

<font size=4>xaxis和yaxis支持的属性是一样,都是坐标轴,就一起说了。</font>

<font size=4 color="green">anchor:锚点</font>

<font size=4 color="green">autorange:自动范围</font>

<font size=4>默认为True,绘制的图表显示的坐标轴的范围会和数据集的范围大致匹配。</font>

<font size=4 color="green">calendar:日历模式</font>

<font size=4 color="green">color:颜色,针对于当前坐标轴的刻度</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"color": "red"}
                                              })
fig

<font size=4 color="green">dtick:坐标刻度的步进值</font>

<font size=4>很重要的一个参数,我们说它描述的是坐标轴上坐标的紧密程度,一般会搭配range来使用。</font>

<font size=4 color="green">range:坐标轴范围</font>

<font size=4>如果是m到n,那么就是"range": [m, n],再搭配dtick,假设为1。那么坐标轴就是m、m+1、m+2、......、n,两者搭配可以对坐标轴刻度做任意的调整。</font>

<font size=4 color="green">fixedrange:固定坐标轴范围</font>

<font size=4>我们说交互式下绘制的图表的坐标轴只会显示和数据集接近的一部分,但是我们可以对坐标轴进行拖拽让它显示其它的部分,如果设置fixedrange为False,那么就不可拖拽,默认是True。</font>

<font size=4 color="green">gridcolor:网格线颜色</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"gridcolor": "yellow"}
                                              })
fig

<font size=4 color="green">gridwidth:网格线宽度</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"gridwidth": 5, "gridcolor": "cyan"}
                                              })
fig

<font size=4 color="green">hoverformat:鼠标指针悬停格式</font>

<font size=4 color="green">linecolor、linewidth:坐标轴线条颜色与宽度</font>

<font size=4>这两个放在一起说,因为一起演示效果更明显。</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"linecolor": "yellow", "linewidth": 5}
                                              })
fig

<font size=4 color="green">nticks:坐标轴呈现多少个刻度</font>

<font size=4>个人觉得和dtick有点重合,range的范围再除以dtick就等同于nticks。因此不指定步进值,也可以直接指定坐标轴上的刻度数。</font>

<font size=4 color="green">rangeslider:范围滑块</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"rangeslider": {"bgcolor": "cyan"}}
                                              })
fig

<font size=4>下方有一个滑块,可以拖动,然后显示对应的图形部分。</font>

<font size=4 color="green">showgrid:显示网格</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"showgrid": False},
                                               "yaxis": {"showgrid": False}
                                              })
fig

<font size=4 color="green">showline:显示线条开关</font>

<font size=4 color="green">side:设置坐标轴刻度位置</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"side": "top"},
                                               "yaxis": {"side": "right"}
                                              })
fig

<font size=4 color="green">spikecolor:峰值数据颜色</font>

<font size=4 color="green">tickangle:刻度角度,之前用过的。</font>

<font size=4 color="green">tickangle:刻度角度,之前用过的。</font>

<font size=4 color="green">tickprefix、ticksuffix:刻度前缀和后缀</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"tickprefix": "<<", "ticksuffix": ">>"},
                                              })
fig

<font size=4 color="green">title、titlefont:等价于layout中的xaxis_title或yaxis_title、标题字体</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"title": "x轴描述", "titlefont": {"color": "cyan", "size": 30}},
                                              })
fig

<font size=4 color="green">type:刻度类型,可以是'-', 'linear', 'log', 'date', 'category', 'multicategory'之一</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"type": "category"}
                                              })
fig

<font size=4 color="green">zeroline:是否显示零线、就是值全部为0的线,对于xaxis就是y轴,对于yaxis就是x轴。</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"zeroline": False},
                                               "yaxis": {"zeroline": False},
                                              })
fig

<font size=4 color="green">zerolinecolor、zerolinewidth:零线的颜色和宽度</font>

random_x = np.linspace(0, 2, 100)  # 生成100个点
random_y0 = np.random.randn(100) + 5
random_y1 = np.random.randn(100) - 5

trace0 = go.Scatter(
    x=random_x,  
    y=random_y0, 
)

trace1 = go.Scatter(
    x=random_x,  
    y=random_y1, 
)


fig = go.Figure(data=[trace0, trace1], layout={"xaxis": {"zerolinecolor": "cyan", "zerolinewidth": 5},
                                               "yaxis": {"zerolinecolor": "pink", "zerolinewidth": 5},
                                              })
fig

保存图表

<font size=4>我们上面就介绍完了大部分内容,一些参数什么的,下面我们还需要将图表保存起来。</font>

保存为html

<font size=4>保存图表可以保存为html,但是html显示的不是图片,而是js生成的可以动态交互的数据,所以保存的html会非常大,大概几M。</font>

# 保存成html有两种方式
fig.write_html("xxx.html")  # 直接通过fig.write_html

# 还可以导入一个模块
import plotly.io as pio
pio.write_html(fig, "xxx.html")

# 两种方式都是可以的

保存为json

<font size=4>将图表保存为json的格式,里面主要是图表的核心数据。</font>

fig.write_json("xxx.json")  
# 或者
import plotly.io as pio
pio.write_json(fig, "xxx.json")

保存为图片

<font size=4>保存为图片应该是最常用的,因为很多时候我们绘制完图表之后需要展示在网页上或者做其它的什么事情,总是就是需要一个图片。</font>

<font size=4>保存为图片稍微有点复杂,这也是没有放在第一个说的原因。因为保存为html、json直接保存即可,但是保存为图片不行,需要一个东西,叫orca。估计很多小伙伴在保存为图片的时候都遇到这个问题:</font>

# 保存方式,三者都是类似的
fig.write_image("xxx.png")  

# 或者
import plotly.io as pio
pio.write_image(fig, "xxx.png")

# 然鹅会报出如下错误
"""
...
...
...
If you haven't installed orca yet, you can do so using conda as follows:

    $ conda install -c plotly plotly-orca

Alternatively, see other installation methods in the orca project README at
https://github.com/plotly/orca

After installation is complete, no further configuration should be needed.

If you have installed orca, then for some reason plotly.py was unable to
locate it. In this case, set the `plotly.io.orca.config.executable`
property to the full path of your orca executable. For example:

    >>> plotly.io.orca.config.executable = '/path/to/orca'

After updating this executable property, try the export operation again.
If it is successful then you may want to save this configuration so that it
will be applied automatically in future sessions. You can do this as follows:

    >>> plotly.io.orca.config.save()

If you're still having trouble, feel free to ask for help on the forums at
https://community.plot.ly/c/api/python

"""

<font size=4>原因就在于你没有安装orca,所以我们需要安装一下。</font>

<font size=4 color="green">Windows安装orca</font>

<font size=4>首先要pip3 install psutil requests,然后我们需要去https://github.com/plotly/orca/releases上面下载对应操作系统的orca安装文件,各种系统都有。我们需要下载Windows版本的orca安装文件,下载之后是一个zip包。解压即可,然后安装的exe文件就在里面,点击安装,然后将安装之后的目录添加到环境变量里面即可。但是我这里直接将安装文件和安装之后的目录提供给你们,可以直接从百度云下载即可。</font>

<font size=4>下面的orca.exe就是安装的exe文件,上面的orca目录就是安装之后的结果,这两个东西的百度云链接如下,我也放在了一个zip包里面。</font>

链接:https://pan.baidu.com/s/1zehUeRC3U5jdmxdHIwtl8A 
提取码:pi30 

<font size=4>下载下来之后解压,你可以点击orca.exe重新安装,也可以不用管那个exe文件,而是直接把上面orca目录设置到环境变量里面即可,因为orca就是orca.exe安装之后的目录,这两个东西我都提供了。个人建议直接把orca目录设置到环境变量里面就行,没必要再单独安装了。</font>

<font size=4>就是这位老铁所在的目录,生成图片就全靠它了。</font>

<font size=4 color="green">Linux安装orca</font>

<font size=4>首先还是要pip3 install psutil requests安装这两个包,然后:</font>

# 安装下面这些,不管有没有,最好都执行一下
yum install fuse-libs-2.9.2-11.el7.x86_64
yum install gtk2-2.24.31-1.el7.x86_64
yum install desktop-file-utils 
yum install Xvfb
yum install xdg-utils-1.1.0-0.17.20120809git.el7.noarch

<font size=4>然后下载orca,这个是绘制成图表所必须的</font>

# 还是去https://github.com/plotly/orca/releases页面下载orca,只不过是linux版本的,后缀是AppImage
# 执行以下命令,就是上面下载的文件
xvfb-run -a xxx.AppImage "$@"
# 然后改个名
mv xxx.AppImage orca
# 赋予执行权限
chmod 755 orca
# 添加到环境变量,输入orca --help查看
# 正常输出,则安装成功

<font size=4 color="green">Mac安装orca</font>

<font size=4>mac安装orca,我没有试过,但是下载mac版本的orca还是去我们上面说的那个页面。具体怎么安装可以网上搜索,嘿嘿,让人怪不好意思的(手动表情包)</font>

<font size=4>安装之后,我们就可以保存图片啦。另外除了write_image,还有一个to_image,这个不需要保存的文件名,而是调用之后直接返回图片的字节流,相当于使用rb模式对图片进行读取。比起图片本身,我们可能更常用字节流,直接渲染到页面上,或者生成base64字节。同理还有to_html、to_json,可以自己尝试一下。另外:to_image同样需要orca,而to_html和to_json则不需要</font>

真的是总结

<font size=4>plotly真的是一个绘图神器,我们中间说的好多一些画布、坐标轴的属性,图表我们只介绍了几个基础的,里面的参数也只说了一部分。至于其它的图表可以去官网查看,支持很多的图表。加油,拥抱plotly吧。不过最让我满意的就是,居然可以嵌入图片作为背景。</font>

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!