如何根据Classification列值为Plotly垂直矩形着色?
问题描述
尝试用Plotly创建包含散点图和垂直矩形(表示事件时长)的图表,希望根据Classification列给矩形设置不同颜色,但循环中设置fillcolor时出现KeyError: 'Classification';固定颜色为'red'时可正常显示,但所有矩形颜色一致。
数据结构
df1
Datetime, Frequency_hz 15/08/2023 09:09:22, 1575422000 15/08/2023 10:10:32, 1575452000 15/08/2023 10:10:35, 1572322000 15/08/2023 11:11:54, 1575432000
events_df
Date_Start_Time, Date_End_Time, Classification, Band 15/08/2023 09:23:22,15/08/2023 09:35:12, Class 1,A 15/08/2023 09:43:40,15/08/2023 09:50:47, Class 2,A 15/08/2023 10:13:44,15/08/2023 10:15:32, Class 3,A 15/08/2023 11:33:11,15/08/2023 11:39:23, Class 4,B
报错代码
# Loading data DATA = 'C:\work\20230815_UTC.csv' EVENT_DATA = r"C:\work\events.csv" BAND = 'A' df = pd.read_csv(DATA) events_df = pd.read_csv(EVENT_DATA) # Filter for band events_df = events_df[(events_df['Band'] == BAND)] # Filter data for specific weekday events_df = events_df.loc[events_df['Date_Start_time'].dt.weekday == 1] # 1= Tues, 2=Wed, 3=Thurs df = pd.read_csv(DATA) # Create plots fig1 = go.Figure() fig1.add_scatter( x=df1.Datetime, y=df1.Frequency_hz, mode="markers", name="Points", showlegend=True ) # Dictionary for colouring classes colours = {'Class 1':'red','Class 2':'violet', 'Class 3':'aqua','Class 4':'brown'} # Loop through events table and plot for i in events_df.index: start_time = events_df.loc[i,"Date_Start_time"] end_time = events_df.loc[i,"Date_End_time"] colour = events_df.loc[i,"Classification"] fig1.add_vrect(x0=start_time, x1=end_time, fillcolor=colours['Classification'], opacity=0.5, name='Events' ) # Update various layout parameters fig1.update_layout( title=f"Events on 15th August 2023", xaxis_title="Time (UTC)", yaxis_title="Frequency (Hz)", font=dict( family="Courier New, monospace", size=18, color="RebeccaPurple" ) ) fig1.show()
解决方案
1. 修复KeyError核心问题
报错原因是你在fillcolor=colours['Classification']中用字符串'Classification'作为字典键,但颜色字典colours的键是'Class 1'这类分类值,而非列名。你已经获取了当前行的分类值并存入colour变量,直接用该变量作为键即可:
fillcolor=colours[colour],
或直接读取当前行的分类值:
fillcolor=colours[events_df.loc[i,"Classification"]],
2. 修复日期类型转换问题
代码中直接调用events_df['Date_Start_time'].dt.weekday会报错,因为pd.read_csv默认将日期列读取为字符串,需先转换为datetime类型;同时注意原数据列名是Date_Start_Time(大写T),代码中误用了Date_Start_time(小写t),需统一:
# 转换日期列为datetime类型,统一列名 events_df['Date_Start_time'] = pd.to_datetime(events_df['Date_Start_Time']) events_df['Date_End_time'] = pd.to_datetime(events_df['Date_End_Time']) df['Datetime'] = pd.to_datetime(df['Datetime'])
3. 其他优化点
- 移除重复的
df = pd.read_csv(DATA)代码; - 修正散点图中变量名不一致问题(代码中定义
df但使用df1); - 将矩形的
name设置为当前分类值,让图例区分不同类别的事件。
修改后的完整代码
import pandas as pd import plotly.graph_objects as go # Loading data DATA = r'C:\work\20230815_UTC.csv' # 加r避免路径转义问题 EVENT_DATA = r"C:\work\events.csv" BAND = 'A' df = pd.read_csv(DATA) events_df = pd.read_csv(EVENT_DATA) # 转换日期列为datetime类型,统一列名 events_df['Date_Start_time'] = pd.to_datetime(events_df['Date_Start_Time']) events_df['Date_End_time'] = pd.to_datetime(events_df['Date_End_Time']) df['Datetime'] = pd.to_datetime(df['Datetime']) # Filter for band events_df = events_df[(events_df['Band'] == BAND)] # Filter data for specific weekday events_df = events_df.loc[events_df['Date_Start_time'].dt.weekday == 1] # 1= Tues, 2=Wed, 3=Thurs # Create plots fig1 = go.Figure() fig1.add_scatter( x=df.Datetime, y=df.Frequency_hz, mode="markers", name="Points", showlegend=True ) # Dictionary for colouring classes colours = {'Class 1':'red','Class 2':'violet', 'Class 3':'aqua','Class 4':'brown'} # Loop through events table and plot for i in events_df.index: start_time = events_df.loc[i,"Date_Start_time"] end_time = events_df.loc[i,"Date_End_time"] colour = events_df.loc[i,"Classification"] fig1.add_vrect(x0=start_time, x1=end_time, fillcolor=colours[colour], opacity=0.5, name=colour # 图例显示分类名称 ) # Update various layout parameters fig1.update_layout( title=f"Events on 15th August 2023", xaxis_title="Time (UTC)", yaxis_title="Frequency (Hz)", font=dict( family="Courier New, monospace", size=18, color="RebeccaPurple" ) ) fig1.show()
内容的提问来源于stack exchange,提问作者cappo
相关产品推荐
相关产品推荐

