Python Forum
Floor division problem with plotting x-axis tick labels
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Floor division problem with plotting x-axis tick labels
#1
Because of the issue I posted about a couple weeks (?) ago regarding matplotlib's asymmetric plotting of x-axis labels (for me, they were at locations of the 1st and 22nd of each month), I'm trying a different approach. Here's some code:

import matplotlib

a = ['2017-01-06', '2017-01-13', '2017-01-20', '2017-01-27', '2017-02-03', '2017-02-10', '2017-02-17', \
     '2017-02-24', '2017-03-03', '2017-03-10', '2017-03-17', '2017-03-24', '2017-03-31', '2017-04-07', \
     '2017-04-14', '2017-04-21', '2017-04-28', '2017-05-05', '2017-05-12', '2017-05-19']
b = [433, 1216, 1234, 2175, 2825, 3271, 3240, 2979, 2234, 3114, 3139, 2975, 3831, 3758, 4127, 4900, 4216,\
     4785, 4043, 4346]
fig, ax = plt.subplots(1)
ax.plot(a,b) 
ax.xaxis.set_major_locator(matplotlib.ticker.FixedLocator([x for x in range(len(a)) if x%(len(a)//3)== 0]))
plt.xticks(rotation=90) 
plt.show()
What I'm trying to get is n tick labels where n is the divisor as shown in the L10 list comprehension.

len(a) = 20. If I want 3 total tick labels then I divide 20 / 3 = 6.67, round that down to 6, and count every sixth week including the first: 2017-01-06, 2017-2-17, 2017-3-31, 2017-5-12. Whoops, that's four tick labels not three! This is exactly what I get, too. //4 plots 4 tick labels and //5 plots 5 tick labels as I'd like. //6 gives 7 tick labels, though.

I suspect the problem here is with the floor division operation, but I need to have an integer divisor for %.

The following works for 1-5 but dividing by 6 or 7 both plot 7 tick labels::

ax.xaxis.set_major_locator(matplotlib.ticker.FixedLocator([x for x in range(len(a)) if x%(round(len(a)/6,0))== 0]))
Can you articulate what I'm overlooking in my logic? Thanks!
Reply
#2
Between n+1 dates, there are n intervals of dates. I suggest to take (len(a) - 1)//(n - 1). For example
>>> (20-1)//(3-1)
9
this would take a[0], a[9], a[18]
Reply
#3
If I want to see n tick labels, this doesn't work for n = 6:

ax.xaxis.set_major_locator(matplotlib.ticker.FixedLocator([x for x in range(len(a)) if x%((len(a)-1)//(6-1))== 0]))
This results in seven tick labels.

Thinking out loud, x will count from 0 to 19 starting at 0. 0%anything == 0 so we get the first tick label. Then we get no remainder when x = 3, 6, 9, 12, 15, and 18 (since 18 // 5 == 3), which is seven tick labels total.
Reply
#4
The following code shows that for evenly spaced tick labels having integer coordinates, only certain numbers of tick labels are possible. For example it is impossible to have 6 or 8 evenly spaced tick labels
>>> for k in range(1, 20):
...     L = list(range(0, 20, k))
...     print(len(L), L)
... 
20 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
10 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
7 [0, 3, 6, 9, 12, 15, 18]
5 [0, 4, 8, 12, 16]
4 [0, 5, 10, 15]
4 [0, 6, 12, 18]
3 [0, 7, 14]
3 [0, 8, 16]
3 [0, 9, 18]
2 [0, 10]
2 [0, 11]
2 [0, 12]
2 [0, 13]
2 [0, 14]
2 [0, 15]
2 [0, 16]
2 [0, 17]
2 [0, 18]
2 [0, 19]

Why not use numpy.linspace to get a sequence of evenly spaced real numbers having a given length?
>>> np.linspace(0, 20, 6)
array([ 0.,  4.,  8., 12., 16., 20.])
>>> np.linspace(0, 19, 6)
array([ 0. ,  3.8,  7.6, 11.4, 15.2, 19. ])
Reply
#5
(Mar-30-2022, 06:41 PM)Gribouillis Wrote: The following code shows that for evenly spaced tick labels having integer coordinates, only certain numbers of tick labels are possible. For example it is impossible to have 6 or 8 evenly spaced tick labels
That's good stuff. There is no 6, for example, and I get 7 instead.

So I have done a poor job articulating what I want. I have in my head what I want to see and I haven't expressed it well in words or in the flawed code I proposed. What I was hoping for was constant spacing with the final number being the lowest possible. So for 2 tick labels, I want [0,10]. For 3 tick labels, I want [0,7,14]. For 4 tick labels, I want [0, 5, 10, 15]. For 5 tick labels it has to be [0, 4, 8, 12, 16]. For 6 there is none and that's why it doesn't work.

So I'll stop banging myself over the head for being dumb on this. This is a nifty three lines of code you put together that nicely shows the possibilities. Thanks!

(Mar-30-2022, 06:48 PM)Gribouillis Wrote: Why not use numpy.linspace to get a sequence of evenly spaced real numbers having a given length?
I like that better! This is outstanding to see the differences:

import matplotlib

a = ['2017-01-06', '2017-01-13', '2017-01-20', '2017-01-27', '2017-02-03', '2017-02-10', '2017-02-17', \
     '2017-02-24', '2017-03-03', '2017-03-10', '2017-03-17', '2017-03-24', '2017-03-31', '2017-04-07', \
     '2017-04-14', '2017-04-21', '2017-04-28', '2017-05-05', '2017-05-12', '2017-05-19']
b = [433, 1216, 1234, 2175, 2825, 3271, 3240, 2979, 2234, 3114, 3139, 2975, 3831, 3758, 4127, 4900, 4216,\
     4785, 4043, 4346]
fig, axs = plt.subplots(20, figsize=(15, 120)) #second arg of figsize allows this to be tall enough for all subplots

for i in range(20):
    plt.sca(axs[i]) #this allows plt.xticks to be applied to every subplot
    axs[i].plot(a,b) 
    axs[i].xaxis.set_major_locator(matplotlib.ticker.FixedLocator(np.linspace(0,19,i)))
    plt.xticks(rotation=90) 
plt.tight_layout()
plt.show()
Reply
#6
(I'm going to move this to a new thread because it's no longer about floor division anymore)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Get numpy ceil and floor value for nearest two decimals klllmmm 4 1,283 Jun-07-2023, 07:35 AM
Last Post: paul18fr
  Division questions Dionysis 5 1,057 Feb-14-2023, 02:02 PM
Last Post: Dionysis
  Floor approximation problem in algorithm gradlon93 3 959 Dec-14-2022, 07:48 PM
Last Post: Gribouillis
  How can histogram bins be separated and reduce number of labels printed on x-axis? cadena 1 894 Sep-07-2022, 09:47 AM
Last Post: Larz60+
  Division by zero and value of argument Lawu 5 3,149 Jul-01-2022, 02:28 PM
Last Post: Lawu
  Points not plotting with reference to x-tick labels Mark17 2 1,279 Jun-14-2022, 05:38 PM
Last Post: Mark17
  How to avoid the extra set of y-axis labels? Mark17 9 2,397 May-17-2022, 06:26 PM
Last Post: Mark17
  How to get evenly-spaced datetime tick labels regardless of x-values of data points? Mark17 4 5,258 Apr-04-2022, 07:10 PM
Last Post: Mark17
  x-axis labels with Matplotlib Mark17 8 2,242 Mar-23-2022, 06:10 PM
Last Post: Mark17
  Sample labels from excel file in order to put them on x-axis and y-axis of a plot hobbyist 11 4,394 Sep-14-2021, 08:29 AM
Last Post: hobbyist

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020