0

I have the following code:

import matplotlib
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MaxNLocator
import math


filename = "populations.txt"

data = np.loadtxt(filename, usecols = 0)
year = data

data = np.loadtxt(filename, usecols = 1)
hares = data

data = np.loadtxt(filename, usecols = 2)
lynxes = data

data = np.loadtxt(filename, usecols = 3)
carrots = data

fig, axes = plt.subplots(nrows=3, figsize=(10,6))

axes[0].plot(year,hares)
axes[0].set_ylim([0,80000])

axes[1].plot(year,lynxes)
axes[1].set_ylim([0,80000])

axes[2].plot(year,carrots)
axes[2].set_ylim([0,80000])

axes[0].xaxis.set_major_locator(MaxNLocator(integer=True))

populations.txt

# year  hare    lynx    carrot
1900    30e3    4e3 48300
1901    47.2e3  6.1e3   48200
1902    70.2e3  9.8e3   41500
1903    77.4e3  35.2e3  38200
1904    36.3e3  59.4e3  40600
1905    20.6e3  41.7e3  39800
1906    18.1e3  19e3    38600
1907    21.4e3  13e3    42300
1908    22e3    8.3e3   44500
1909    25.4e3  9.1e3   42100
1910    27.1e3  7.4e3   46000
1911    40.3e3  8e3 46800
1912    57e3    12.3e3  43800
1913    76.6e3  19.5e3  40900
1914    52.3e3  45.7e3  39400
1915    19.5e3  51.1e3  39000
1916    11.2e3  29.7e3  36700
1917    7.6e3   15.8e3  41800
1918    14.6e3  9.7e3   43300
1919    16.2e3  10.1e3  41300
1920    24.7e3  8.6e3   47300

Plot results

How can I force the year labels on the x-Axis to be integers from 1900 to 1920 (as saved accordingly in the "year" array), and why are they being displayed as floats in the first place?

I attempted to force the matter in the axes[0] plot but that seems to have just caused other issues. What am I missing?

Ideally, I'd prefer to also not have to hardcode 1900 - 1920 as the year span, because the dataset may grow. How might I make sure np.loadtxt() saves the data as integers right from the start so that this integer/float labelling issue never arises in the first place? dtype = np.int isn't changing anything unfortunately.

Thanks!

Liam
  • 3
  • 2
  • Thanks for the suggestion! Unfortunatly `dtype=np.int` changes nothing in the axis labelling. The `set_xticks` work well, however if the population dataset grew to include more years, they wouldn't change with it. I'd prefer not to hardcode the year span. `dtype=np.int` sounds much more like what I need, but it seems to have no effect. – Liam Feb 24 '20 at 23:18
  • That's a good idea, but: **'numpy.float64' object cannot be interpreted as an integer**. My takeaway from that is that the issue that needs to be sorted is how to prevent the arrays from becoming float arrays in the first place, especially considering the data is all integers. Maybe there's another method of loading in text file data that doesn't default to float? – Liam Feb 24 '20 at 23:32
  • Well, do both the `dtype=np.int` when reading the year, and `ax.set_xticks(range(min(year), max(year)+1, 2)` or `ax.set_xticks(range(int(min(year)), int(max(year))+1, 2)` – JohanC Feb 24 '20 at 23:36
  • Et Voila! You're my hero <3 Thanks! – Liam Feb 24 '20 at 23:40

2 Answers2

0

Welcome to Stackoverflow.

You can do this by importing the math module or just using range if you are manually specifying inputs.

import math
y_vals = range(math.floor(min(0)), math.ceil(max(80000))+1)

add the y_vals when you are setting yticks. I added the math functions there in case you deal with other values that you don't enter manually and I had referenced this answer in the past. You could just as easily do range(0, 80001) instead and it will work.

then it is:

axes[0].set_yticks(y_vals)

and do that for all axes.

Rahul P
  • 2,493
  • 2
  • 17
  • 31
  • Thanks! I got the following error using your suggestion: 'int' object is not iterable. When I removed the math functions though and just did: `x_vals = range(1900, 1921, 2) axes[0].set_xticks(x_vals)` It gave me exactly what I needed. I really appreciate the help, thanks! :) – Liam Feb 24 '20 at 23:01
  • Although - that solution does require me to hardcode in the year span so it wouldn't work if the data set grew to include more years... Ideally I could just force the int array at the time np.loadtxt() is called. There has to be some way to do it. dtype=np.int doesn't seem to be working though – Liam Feb 24 '20 at 23:21
0

Solved by JohanC in the comments:

Well, do both the dtype=np.int when reading the year, and ax.set_xticks(range(min(year), max(year)+1, 2) or ax.set_xticks(range(int(min(year)), int(max(year))+1, 2)

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Liam
  • 3
  • 2