0

I am plotting a joyplot where the x-axis is a range of dates. However, joyplot only accepts dates arguments as numbers... As a result, the chart is plotted correctly, but the x-axis displays dates as their serial number, which is not very friendly to the end user.

I have tried various methods to format the axis (like this one: Set x axis labels for joyplot), but none worked so far!

How can I format the x-axis so that it displays dates in the 'mm.yyyy' format (eg.: 01.2022)?

I am using the following database to plot this example (saved as a .csv to my computer): https://www.boxofficemojo.com/genre/sg4242469121/?ref_=bo_gs_table_24

Table example (copy it and paste in a .csv file, naming it "Example", as in code below):

Title Release Date Date Distributor
Incredibles 2 Jun 15, 2018 43252 Walt Disney Studios Motion Pictures
The Lion King Jul 19, 2019 43647 Walt Disney Studios Motion Pictures
Finding Dory Jun 17, 2016 42522 Walt Disney Studios Motion Pictures
Frozen II Nov 22, 2019 43770 Walt Disney Studios Motion Pictures
Shrek 2 May 19, 2004 38108 DreamWorks
Toy Story 4 Jun 21, 2019 43617 Walt Disney Studios Motion Pictures
Toy Story 3 Jun 18, 2010 40330 Walt Disney Studios Motion Pictures
Frozen Nov 22, 2013 41579 Walt Disney Studios Motion Pictures
The Secret Life of Pets Jul 8, 2016 42552 Universal Pictures
Despicable Me 2 Jul 3, 2013 41456 Universal Pictures
Inside Out Jun 19, 2015 42156 Walt Disney Studios Motion Pictures
Zootopia Mar 4, 2016 42430 Walt Disney Studios Motion Pictures
Finding Nemo May 30, 2003 37742 Walt Disney Studios Motion Pictures
Minions Jul 10, 2015 42186 Universal Pictures
Shrek the Third May 18, 2007 39203 DreamWorks
The Lion King Jun 15, 1994 34486 Walt Disney Studios Motion Pictures
Up May 29, 2009 39934 Walt Disney Studios Motion Pictures
Minions: The Rise of Gru Jul 1, 2022 44743 Universal Pictures
The Grinch Nov 9, 2018 43405 Universal Pictures
Sing Dec 21, 2016 42705 Universal Pictures
Monsters University Jun 21, 2013 41426 Walt Disney Studios Motion Pictures

Code:

import joypy
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

%matplotlib inline

df = pd.read_csv(r'C:\Users\Downloads\Example.csv', delimiter=';') #replace file name and directory with your file, created from the table above
print(df.shape)
df.head()

fig, ax = joypy.joyplot(df, 
                        by = 'Distributor', 
                        column='Date', 
                        colormap=cm.autumn, 
                        figsize = (10,6),
                        fade = True)

Output plot:

enter image description here

M_B
  • 47
  • 7
  • That file doesn't exist on my system – Paul H Jul 21 '22 at 18:21
  • Sorry, I edited the question and inserted table containing a sample of the data (just some lines of the table contained in the link of the question, I think it suffices for a simple test). You must copy it and save as a .csv in your computer. – M_B Jul 21 '22 at 21:18
  • I think you want to employ the `parse_dates` kwarg in `pandas.read_csv` – Paul H Jul 21 '22 at 22:42
  • I tried it before... It gives the following error: "No numeric values found. Joyplot requires at least a numeric column/group". The plot only works when I transform the dates to numbers in the source (i.e., make 'Jun 15, 2018' = 43252). But then I don't want the xticks to retain this 'weird' look, I need it to display a date, like '06.2018' – M_B Jul 21 '22 at 23:45

2 Answers2

1

I managed to get the dates in the x-axis with help from the link you provided. I wanted to go through it in a bit of detail here.

Code for reading and formatting data

As joyplot only takes numbers, I converted the strings (Jan2, 2018 format) to dates and put them in Date column. Then to numbers using ordinal. I mention this because the numbers above are slightly different. It should not matter...

import joypy
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

%matplotlib inline

df = pd.read_excel('example.xlsx') ## Copy pasted data into excel
df['Date'] = pd.to_datetime(df['Release Date'], format = '%b %d, %Y')
df['Date_Number'] = df['Date'].apply(lambda x:x.toordinal())

Create array to be used for axis

This is similar to what was in the other SO post. But, the data was from some time in 1991 to 2023. So, hardcoded them. Used 9 ticks as I thought that the 32 years would blend well having 8 interim labels. Also, used -12 so that just the year and month would show up. I think as all are Jan, you can remove that as well. Will leave it up to you...

# Generate date strings from a manually set start date
numdays = 9
start_date = "01-Jan-1991"
dates = pd.date_range(start = "01-Jan-1991", end ='01-Jan-2023',periods=numdays)
dates = [str(date)[:-12] for date in dates]

Plot graph and adjust the axis

As in the other post, used ax[-1] to get the last axis. But do note that I have used the set_ticks() to get the ticks, then the set_ticklables() for the labels and finally the xlim() to set the ends of the start and end points, like so...

fig, ax = joypy.joyplot(df,  by = 'Distributor', column='Date_Number', 
                        colormap=matplotlib.cm.autumn, figsize = (10,6), fade = True)

ax[-1].set_xticks(range(numdays))
ax[-1].set_xticklabels(dates)
ax[-1].set_xlim([0, 8])

...and the resulting plot is

enter image description here

Redox
  • 9,321
  • 5
  • 9
  • 26
1

First, please accept that the x-axis tick values in my answer may not be correct; it is unclear what the value obtained by ax[-1].get_xticks() indicates. Assuming it represents days, I can change it to a date in the following way: since the time series in maplotlib is Gregorian standard, I convert it from a number to a date.

df['Release Date'] = pd.to_datetime(df['Release Date'], format='%b %d, %Y')

import joypy
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.dates as mdates
%matplotlib inline

fig, ax = joypy.joyplot(df, 
                        by = 'Distributor', 
                        column='Date', 
                        colormap=cm.autumn, 
                        figsize = (10,6),
                        xrot=45,
                        fade = True)

print(ax[-1].get_xticks())
new_dates = [mdates.num2date(x +  mdates.date2num(np.datetime64('1900-01-01'))) for x in ax[-1].get_xticks()]
new_dates = [t.strftime('%b-%Y') for t in new_dates]
ax[-1].set_xticklabels(new_dates)

fig.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32