Reputation: 837
I have the following data.
I am using a slider, so that I can slide through the different dates (please see the picture below to see what a slider is in case).
Now, as my category may change between the dates I want to initialize my x-axis range with A,B,C,E,F no matter what my date is. So sometimes I will have no data points in a category but this does not matter to me.
So how can initialize my x-axis range and make my data points adapt to the initialized x-axis?
I am using python3 and plotly express.
This is my code for now :
data.columns = ['price', 'category', 'date']
data = data.sort_values(by=['date', 'price'])
fig = px.scatter(data, x = "category", y = "price", animation_frame="date")
fig.update_layout(
yaxis_title="Price (€)",
)
fig['layout']['updatemenus'][0]['pad']['t'] = 180
fig['layout']['sliders'][0]['pad']['t'] = 200
fig.write_html("/home/**/Desktop/1.html", auto_play=True)
Ihope I was clear enough. Please let me know if you need any extra information. Any ideas or tips is welcome :)
Upvotes: 4
Views: 5378
Reputation: 61094
The only way you can make sure that all categories are represented on the x-axis for all animation frames is to make sure they appear in the first Date = X
. So you can't actually fix the x-axis ranges in the figure itself. You'll have to do it through your representation of the data source.
So sometimes I will have no data points in a category but this does not matter to me.
Maybe not, but it will matter to plotly.express. Particularly if you by "have no data" mean that you do not have records for all categories in your dataset for all dates. You see, plotly seems to set the x-axis values to the categories it finds in the first unique values for Date = X
which is A, B ,C
. But don't worry, we'll handle that too. Let's use a slightly altered version of your data screenshot (next time, do this). I've added actual dates instead of X, Y
and reduced the range of the numbers a bit since your particular data messes up the animation a bit.
If we use an animation approach like this:
fig = px.scatter(df1, x="Category", y="Price", animation_frame="Date",
color="Category", range_y=[0,20])
... you'll get two animation frames:
Now, lets use an approach to make sure alle categories are represented for all dates as you can find in the post Pandas: How to include all columns for all rows although value is missing in a dataframe with a long format?
Now you'll get:
I hope this is what you were looking for. Don't hesitate to let me know if not!
You'll get a slightly different result if you drop the df1.fillna(0)
part. But I'll leave it up to you to mess around with all available options in the
import pandas as pd
import plotly.express as px
df = pd.DataFrame({'Date': {0: '24.08.2020',
1: '24.08.2020',
2: '24.08.2020',
3: '25.08.2020',
4: '25.08.2020',
5: '25.08.2020'},
'Category': {0: 'A', 1: 'B', 2: 'C', 3: 'C', 4: 'E', 5: 'F'},
'Price': {0: 1, 1: 2, 2: 3, 3: 3, 4: 10, 5: 13}})
# make sure that all category variables are represented for
# all dates even though not all variables have values.
df['key']=df.groupby(['Date','Category']).cumcount()
df1 = pd.pivot_table(df,index='Date',columns=['key','Category'],values='Price')
df1 = df1.stack(level=[0,1],dropna=False).to_frame('Price').reset_index()
df1 = df1[df1.key.eq(0) | df1['Price'].notna()]
df1=df1.fillna(0)
# ploty express animation
fig = px.scatter(df1, x="Category", y="Price", animation_frame="Date",
color="Category", range_y=[0,20])
# some extra settings.
fig.update_layout(transition = {'duration': 20000})
fig.show()
Upvotes: 3