Plotly:创建具有分类 x 轴抖动和多级轴的 Scatter

Dan*_*ata 5 python graph scatter-plot plotly jitter

我想制作一个多级 x 轴的图形,如下图所示: 多层次分散

import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(
  go.Scatter(
    x = [df['x'], df['x1']],
    y = df['y'],
    mode='markers'
  )
)
Run Code Online (Sandbox Code Playgroud)

但我也想将抖动放在 x 轴上,如下图所示: 在此处输入图片说明

到目前为止,我可以使用下一个代码独立制作每个图形:

import plotly.express as px
fig = px.strip(df,
               x=[df["x"], df['x1']], 
               y="y",
               stripmode='overlay') 
Run Code Online (Sandbox Code Playgroud)

是否可以将抖动和多级轴组合在一个图中?

这是重现数据集的代码:

import numpy as np
import pandas as pd
import random

'''Create DataFrame'''
price = np.append(
  np.random.normal(20, 5, size=(1, 50)), np.random.normal(40, 2, size=(1, 10))
)
quantity = np.append(
  np.random.randint(1, 5, size=(50)), np.random.randint(8, 12, size=(10))
)

firstLayerList = ['15 in', '16 in']
secondLayerList = ['1/2', '3/8']
vendorList = ['Vendor1','Vendor2','Vendor3']

data = {
  'Width':  [random.choice(firstLayerList) for i in range(len(price))],
  'Length': [random.choice(secondLayerList) for i in range(len(price))],
  'Vendor': [random.choice(vendorList) for i in range(len(price))],
  'Quantity': quantity,
  'Price':  price
}
df = pd.DataFrame.from_dict(data)
Run Code Online (Sandbox Code Playgroud)

S3D*_*DEV 5

首先 - 感谢您的挑战!这些天没有多少具有挑战性的 Plotly 问题。

创建带有抖动的散点图的关键要素是:

  • 使用mode: 'box'- 创建箱线图,而不是散点图。
  • 设置'boxpoints': 'all'- 绘制所有点。
  • 使用'pointpos': 0- 使点在 x 轴上居中。
  • 使用以下方法移除(隐藏!)晶须盒:
    • 'fillcolor': 'rgba(255,255,255,0)'
    • 'line': {'color': 'rgba(255,255,255,0)'}

数据帧准备:

此代码简单地将主 DataFrame 拆分为每个供应商的框架,从而允许为每个供应商创建具有自己颜色的跟踪。

df1 = df[df['Vendor'] == 'Vendor1']
df2 = df[df['Vendor'] == 'Vendor2']
df3 = df[df['Vendor'] == 'Vendor3']
Run Code Online (Sandbox Code Playgroud)

绘图代码:

如果您愿意,绘图代码可以使用for-loop。但是,我故意让它更冗长,以增加清晰度。

import plotly.io as pio

layout = {'title': 'Categorical X-Axis, with Jitter'}
traces = []

traces.append({'x': [df1['Width'], df1['Length']], 'y': df1['Price'], 'name': 'Vendor1', 'marker': {'color': 'green'}})
traces.append({'x': [df2['Width'], df2['Length']], 'y': df2['Price'], 'name': 'Vendor2', 'marker': {'color': 'blue'}})
traces.append({'x': [df3['Width'], df3['Length']], 'y': df3['Price'], 'name': 'Vendor3', 'marker': {'color': 'orange'}})

# Update (add) trace elements common to all traces.
for t in traces:
    t.update({'type': 'box',
              'boxpoints': 'all',
              'fillcolor': 'rgba(255,255,255,0)',
              'hoveron': 'points',
              'hovertemplate': 'value=%{x}<br>Price=%{y}<extra></extra>',
              'line': {'color': 'rgba(255,255,255,0)'},
              'pointpos': 0,
              'showlegend': True})

pio.show({'data': traces, 'layout': layout})
Run Code Online (Sandbox Code Playgroud)

图形:

此图表背后的数据是使用np.random.seed(73), 针对问题中发布的数据集创建代码生成的。

在此处输入图片说明

评论 (TL; DR):

此处显示的示例代码使用较低级别的 Plotly API,而不是诸如graph_objects或 之类的便利包装器express。原因是我(个人)认为向用户展示“幕后”发生的事情是有帮助的,而不是用方便的包装器来掩盖底层代码逻辑。

这样,当用户需要修改图形的更精细细节时,他们将对Plotly 为底层图形引擎(orca)构建的lists 和dicts有更好的理解。

这个用例是这种推理的一个主要例子,因为它正在 Plotly 超越其(当前)设计点。

  • 这正是我所需要的!非常感谢@S3DEV 您的帮助! (2认同)