I want to display the x-axis values in my plotly express chart in a standard format, as opposed to having raw labels; while preserving the tick layouts.
Basically, I like the fact there's only a few 'main' ticks and not a tick for every value, but I need to change the text on the labels.
The labels currently are integer values representing milliseconds, I'd like to change these to min:sec:ms, as shown in the image below. Note, the 'Time'
column in 'df'
represents the milliseconds in the correct format.
I have been trying to figure this out using the 'Array' tickmode and sorting, but this either sorts the chart (which I don't want), or the labels generated are unevenly spaced and aren't rounded to the nearest second.
Here is my original code before I messed it up!
import pandas as pd
import numpy as np
import plotly.express as px
from _plotly_utils.colors import n_colors
from scipy import stats
import streamlit as st
def lap_times_graph(year, d_ids, laps_df, races_df, col=st):
for d_id in d_ids:
times = {"x": [], "y": [], "Name": [], "Lap": [], "Time": []}
# Obtains each race the selected driver was in for the selected year
# races_df = races_df.loc[races_df["year"] == year, ["race_id", "name"]]
races_df = races_df[races_df["year"] == year]
for index, r in races_df.iterrows():
df_laps = laps_df.loc[
(laps_df["race_id"] == r["race_id"]) &
(laps_df["driver_id"] == d_id),
["lap", "time", "milliseconds"]
]
df_laps2 = df_laps.sort_values(by="milliseconds")
for ndx, r1 in df_laps.iterrows():
times["x"].append(r1["milliseconds"])
times["y"].append(r["race_id"])
times["Name"].append(r["name"])
times["Lap"].append(r1["lap"])
times["Time"].append(r1["time"])
df = pd.DataFrame(data=times)
# Remove outliers
z = np.abs(stats.zscore(df['x']))
threshold = 3
outliers = df[z > threshold]
df = df.drop(outliers.index)
fig = px.strip(df, x="x", y="y",
title="""Lap Times<br><sub class='subtitle'>"""
"""Hover over points for more details</sub>""",
labels={"x": "Lap time", "y": "Race"},
color_discrete_sequence=n_colors(
"rgb(255, 75, 75)",
"rgb(255,255,255)",
3,
colortype="rgb"
),
color="y",
hover_name="Name", hover_data={
"x": False,
"y": False,
"Lap": True,
"Time": True
})
fig.update_layout(
showlegend=False,
yaxis=dict(
side="right",
showticklabels=False),
xaxis=dict(
tickangle=-45)
)
col.plotly_chart(fig, use_container_width=False)
def run():
laps_data = {
"race_id": [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],
"driver_id": [101, 101, 101, 101, 101, 102, 102, 102, 102, 102],
"lap": [1, 2, 3, 4, 5, 1, 2, 3, 4, 5],
"time": ['1:40.123', '1:38.456',
'1:37.789', '1:36.123',
'1:35.456', '1:41.789',
'1:40.456', '1:39.789',
'1:38.123', '1:37.456'],
"milliseconds": [100123, 98456, 97789, 96123, 95456,
101789, 100456, 99789, 98123, 97456]
}
races_data = {
"race_id": [1, 2],
"name": ['Australian Grand Prix', 'Monaco Grand Prix'],
"year": [2023, 2023]
}
laps_df = pd.DataFrame(laps_data)
races_df = pd.DataFrame(races_data)
year = 2023
driver_ids = [101, 102]
lap_times_graph(year, driver_ids, laps_df, races_df)
Is there any way to change the labels on the default ticks so I don't have to calculate a way to remake them? df["Time"]
Holds values with the correct format I'm looking for.
An example (the x-axis labels) of what I'm looking to achieve (changes in yellow will replace the ticks already there):
Thanks.
UPDATE:
This has been solved by @r-beginners in the comments of my post.
Their solution was the following:
fig.update_xaxes(type='date',tickformat='%M:%S.%f')