Python Forum
x-axis labels with Matplotlib - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: x-axis labels with Matplotlib (/thread-36721.html)



x-axis labels with Matplotlib - Mark17 - Mar-22-2022

Hopefully this isn't too hard to follow.

Fri_2017 is a list of the first 20 Fridays in 2017 as type datetime.datetime .

I also have this:

for i in range(20):
    random_pnl_list.append(random.randint(-1000,1000))
cumul_pnl_from_random = list(np.cumsum(random_pnl_list))
Now... when I do this in matplotlib:

plt.plot(Fri_2017,cumul_pnl_from_random)
I get x-axis labels at the first and 22nd of the first five months (e.g. 2017-01-01, 2017-01-22, 2017-02-01... 2017-05-01, 2017-05-22). How is this determined--both format and those two particular dates of every month?

I also have this line:

converted_Fri_2017 = [d.strftime('%Y-%m-%d') for d in Fri_2017]
When I do:

plt.plot(converted_Fri_2017,cumul_pnl_from_random)
I get x-axis labels of same format as above (yyyy-mm-dd) but every Friday from 1/6/17 through 5/19/17 (20 total labels). Why the difference?


RE: x-axis labels with Matplotlib - deanhystad - Mar-22-2022

You should post your code so others can run it. I tried to duplicate from the description.
import random
import matplotlib.pyplot as plt
import numpy as np
from datetime import date, timedelta

def friday(year):
    day = date(year, 1, 1)
    day += timedelta(days=(4 - day.weekday())%7)
    week = timedelta(weeks=1)
    while day.year == year:
        yield day
        day += week

random_pnl_list = []
for i in range(20):
    random_pnl_list.append(random.randint(-1000,1000))
cumul_pnl_from_random = list(np.cumsum(random_pnl_list))

fridays = list(friday(2017))[:len(cumul_pnl_from_random)]
plt.plot(fridays, cumul_pnl_from_random)
plt.show()
My guess is matplotlib is doing the same kind of thing it does with numbers; picking nice start and stop values that it can divide into evenly sized intervals appropriate for the plot. When you convert the dates to strings they become just that, strings. Matplotlib does not know what they mean, does not know how they should be spaced, and just spaces them evenly without worrying about the "value" of the first or last x value.

Code for getting fridays in "%m-%d" format.
def friday(year):
    day = date(year, 1, 1)
    day += timedelta(days=(4 - day.weekday())%7)
    week = timedelta(weeks=1)
    while day.year == year:
        yield day.strftime('%m-%d')
        # yield day
        day += week



RE: x-axis labels with Matplotlib - Mark17 - Mar-23-2022

Done with the Fri_2017 list, x-axis labels are periodic but asymmetric as the 22nd and 1st are close together followed by a longer space and then another 22nd and 1st, etc. Is this "evenly sized intervals appropriate for the plot?" I would have thought if left to auto scale, matplotlib would have selected intervals that were really evenly spaced out (e.g. every Z x-value increments and since an x-value here is one week, that translates to every Z weeks).

Incidentally, last time I posted a question about matplotlib I didn't get a response and I figured that might have been because the code was too long and messy for people to bother wading through.

Sorry you had to take the time to reconstruct everything, Dean. My code here went something like this:

from datetime import datetime
from datetime import timedelta
import random
import numpy as np
import matplotlib.pyplot as plt

Fri_2017 = [] #2017_Fri gives "invalid decimal literal" at the underscore
random_pnl_list = []
cumul_pnl_from_random = []

start_date = datetime(2017,1,1) #not datetime.datetime()
while True: #True must be capitalized
    if start_date.weekday() == 4:
        Fri_2017.append(start_date)
        break
    else:
        start_date += timedelta(days=1)
for i in range(19):
    Fri_2017.append(Fri_2017[-1] + timedelta(days=7))

converted_Fri_2017 = [d.strftime('%Y-%m-%d') for d in Fri_2017] #list comprehension
print(converted_Fri_2017)

for i in range(20):
    random_pnl_list.append(random.randint(-1000,1000))

cumul_pnl_from_random = list(np.cumsum(random_pnl_list)) #np returns array but this MUCH easier than doing loop to compute
print(random_pnl_list)
print(cumul_pnl_from_random)

fig, [ax1, ax2] = plt.subplots(2)

plt.sca(ax1)
plt.plot(Fri_2017,cumul_pnl_from_random)
plt.xticks(rotation=90)
plt.sca(ax2)
plt.plot(converted_Fri_2017,cumul_pnl_from_random)
plt.xticks(rotation=90)

plt.tight_layout()
plt.show()



RE: x-axis labels with Matplotlib - deanhystad - Mar-23-2022

My version of your code labels the first and fifteenth of each month. Our Fridays must be different.


RE: x-axis labels with Matplotlib - Mark17 - Mar-23-2022

(Mar-23-2022, 02:56 PM)deanhystad Wrote: My version of your code labels the first and fifteenth of each month. Our Fridays must be different.

That makes a lot more sense... 14 days apart followed by another 14-17 days is more evenly spaced than 21 days apart followed by another 8-10 days. Why might this be?

My list is the first 20 Fridays of 2017.


RE: x-axis labels with Matplotlib - deanhystad - Mar-23-2022

Mine are dates, yours are datetimes. Strange that makes a difference.


RE: x-axis labels with Matplotlib - Mark17 - Mar-23-2022

(Mar-23-2022, 05:06 PM)deanhystad Wrote: Mine are dates, yours are datetimes. Strange that makes a difference.

I changed L1 of my code to "from datetime import date" and L11 to "start_date = date(2017,1,1)" The x-axis label output was the same (1st and 22nd of each month) while confirming that Fri_2017 is populated with <class 'datetime.date'> (it was previously <class 'datetime.datetime'>). Does this mean it's something other than date vs. datetime?

By the way, I found this related discussion: https://bit.ly/3tyZHRP One poster also found ticks to fall on 1st and 15th of every month as you did.


RE: x-axis labels with Matplotlib - deanhystad - Mar-23-2022

Must be different versions of something. I run your code and get x ticks on 1 and 15 for the top plot (datetime) and weekly ticks on the bottom plot (strings).


RE: x-axis labels with Matplotlib - Mark17 - Mar-23-2022

(Mar-23-2022, 05:58 PM)deanhystad Wrote: Must be different versions of something. I run your code and get x ticks on 1 and 15 for the top plot (datetime) and weekly ticks on the bottom plot (strings).

Thanks!