1

result

   year  Month  Min_days    Avg_days    Median_days     Count MonthName-Year
    2015   1          9        12.56          10         4     2015-Jan
    2015   2          10       13.67          9          3     2015-Feb
   ........................................................
    2016   12       12       15.788           19          2    2016-Dec
    and so on...

I wish to create a line plot plotting min_days, avg_days, median_days, count according to month and year say. Code used for that(which works perfectly):

import matplotlib.pyplot as plt
result=freq_start_month_year_to_date_1(df,'Jan','2015','Dec','2019')

#Visualisations

fig, ax = plt.subplots()
for col in ["Min_days", "Median_days", "Count",'Target_days_before_customer_dead']:
    ax.plot(result["Month Name-Year"], result[col], label=col)
ax.legend(loc="best")
ax.tick_params(axis="x", rotation=30)

I am getting a plot . The only issue is that the x axis is too crowded and all the values 2015-Jan, 2015-Feb etc are overlapping so nothing is readable in the x axis, it looks like black scrabbling...I am unable to increase the size of the plot.

I tried below code but that too did not work

fig, ax = plt.subplots(2,2, figsize=(20,20))

Using the above code I got 4 empty sub plots

noob
  • 3,601
  • 6
  • 27
  • 73

1 Answers1

1

The problem is you preformatted your x-axis as string and thus robbed matplotlib of the chance to apply its own formatter. matplotlib tried to cram all the strings into the axis so you can never make it wide enough to hold all the labels.

Create a new date column and use it to form your x axis:

from matplotlib import dates as mdates

# The new column to be used as x axis
result['Date'] = pd.to_datetime(result[['Year', 'Month']].assign(Day=1))

# Plot the data
fig, ax = plt.subplots(figsize=(10, 2))
for col in ['Min_days', 'Median_days', 'Count', 'Target_days_before_customer_dead']:
    ax.plot(result['Date'], result[col], label=col)

years = mdates.YearLocator()    # only print label for the years
months = mdates.MonthLocator()  # mark months as ticks
years_fmt = mdates.DateFormatter('%Y')

ax.xaxis.set_major_locator(years)
ax.xaxis.set_minor_locator(months)
ax.xaxis.set_major_formatter(years_fmt)

ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

Result (with random data):

matplotlib result

Code Different
  • 90,614
  • 16
  • 144
  • 163
  • NameError: name 'mdates' is not defined – noob Jan 06 '20 at 15:09
  • Ah, forgot the import: `from matplotlib import dates as mdates` – Code Different Jan 06 '20 at 15:10
  • It works but i need labels too, like which color is for mean, which color is for median etc. 2) What is Day=1, what does it do? Once I get these 2 answers I will mark it as accepted answer since it solves my problem :).. Thanks :) – noob Jan 06 '20 at 15:12
  • Add an `ax.legend` call. For the `Day=1`: you already have the `Year` and `Month` columns. To make a valid date, you also need a Day. `.assign(Day=1)` creates a new `Day` column and assign it to 1 – Code Different Jan 06 '20 at 15:16
  • Lastly is it possible to see the data values while hovering over plots? – noob Jan 06 '20 at 15:28
  • 1
    Yes, but I am not able to work on that right now. See this question: https://stackoverflow.com/questions/7908636/possible-to-make-labels-appear-when-hovering-over-a-point-in-matplotlib – Code Different Jan 06 '20 at 15:32
  • What does .assign(Day=1) do? I am trying to use this code for another question – noob Jan 30 '20 at 10:16
  • It creates a new column called `Day` with the value of 1 for all rows – Code Different Jan 30 '20 at 11:37