当在 x 轴上使用时间数据时,Plotly Express 带状图不会按颜色分隔点。
设置一些具有随机组和状态的数据(这将是我们图中点的颜色)
import pandas as pd
import plotly.express as px
import random
random.seed(0)
n = 100
df = pd.DataFrame(
data=dict(
group=random.choices(["A","B","C"], k=n),
status=random.choices(["on", "off"], k=n),
time=pd.date_range('2/5/2019', periods = n, freq ='2H'),
)
)
我们的数据框是
print(df)
group status time
0 C off 2019-02-05 00:00:00
1 C off 2019-02-05 02:00:00
2 B on 2019-02-05 04:00:00
3 A off 2019-02-05 06:00:00
4 B on 2019-02-05 08:00:00
.. ... ... ...
95 C on 2019-02-12 22:00:00
96 C off 2019-02-13 00:00:00
97 A on 2019-02-13 02:00:00
98 B off 2019-02-13 04:00:00
99 B on 2019-02-13 06:00:00
[100 rows x 3 columns]
当我们以
"time"
为 x 轴,使用 status
作为颜色制作条形图时,所有状态值都位于相同的 y 级别
px.strip(df, x="time", y="group", color="status")
但是如果我们使用 DataFrame 的整数索引作为 x 轴,则颜色会放置在不同的 y 级别上
px.strip(df.reset_index(), x="index", y="group", color="status")
我希望时间数据像整数数据一样绘制(在不同的 y 级别上具有不同的颜色)。我在文档中没有看到任何内容表明时态数据是一个问题。
当然,有一种更简单的方法可以实现您想要的结果,但另一种解决方案是使用整数索引作为 x 轴创建带状图,然后将刻度标签更新为日期时间值。
此解决方案的缺点是,
plotly
通常会自动为您管理某些事情,例如刻度标签间距,现在必须由您的代码手动处理。
这是此方法的源代码:
import plotly.express as px
import pandas as pd
import numpy as np
import random
random.seed(0)
# Assuming df is your DataFrame with a 'time' column containing datetime values,
# 'group' for y-values, and 'status' for coloring.
n = 100
df = pd.DataFrame(
data=dict(
group=random.choices(["A","B","C"], k=n),
status=random.choices(["on", "off"], k=n),
time=pd.date_range('2/5/2019', periods = n, freq ='2H'),
)
)
# Optionally, ensure 'time' is a datetime column
df['time'] = pd.to_datetime(df['time'])
# Create a numeric sequence for the x-axis
numeric_x = np.arange(len(df))
# Create the plot figure
fig = px.strip(df, x=numeric_x, y="group", color="status")
# Format the datetime values as strings
formatted_dates = df['time'].dt.strftime('%b %d<br>%Y')
# Select a subset of formatted datetime values for tick labels to avoid overcrowding
# Here, we select every Nth label, where N depends on the density of your data
N = max(1, len(df) // 5) # Adjust this based on your data density
tick_vals = np.array([*numeric_x[::N], numeric_x[-1]])
tick_texts = np.array([*formatted_dates[::N], formatted_dates.iloc[-1]])
# Set the customized tick labels
fig.update_xaxes(tickvals=tick_vals, ticktext=tick_texts)
# Update layout (optional)
fig.update_layout(
xaxis_title="Time",
yaxis_title="Group Value",
legend_title="Status"
)
# Show the plot
fig.show()
输出: