Reputation: 67
I have two numpy.ndarrays
, bcmonthly
and dailyavg
.
bcmonthly has a length of 12 and shape of (12,)
dailyavg has a length of 364 and shape of (364,)
bcmonthy
is the monthly average and dailyavg
is the daily average. I want to plot the two variables against the x-axis of 12 months.
Plotting bcmonthly
has no issue because its shape is 12. However when I plot dailyavg
simultaneously I get this error:
ValueError: x and y must have same first dimension, but have shapes (12,) and (364,)
Below is my code:
fig = plt.figure()
ax1=fig.add_subplot(111)
ax1.plot(months,bcmonthly,'r') #months is a list months=['jan','feb',..etc]
ax2 = ax1.twinx()
ax2.plot(months, dailyavg)
plt.show()
Upvotes: 1
Views: 2482
Reputation: 248
If you want to plot the daily averages on the same plot with the monthly averages, it may be easier to construct two arrays and plot them both against an array of days and then handle the labeling yourself. Something like this
import matplotlib.pyplot as plt
import numpy as np
bcmonthly = np.random.rand(12) # Creates some random example data,
dailyavg = np.random.rand(365) # use your own data in place of this
days = np.linspace(0, 364, 365)
months = ['January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September',
'October', 'November', 'December']
lmonths = [0, 2, 4, 6, 7, 9, 11]
smonths = [3, 5, 8, 10]
month_idx = list()
idx = -15 # Puts the month avg and label in the center of the month
for jj in range(len(months)):
if jj in lmonths:
idx += 31
month_idx.append(idx)
elif jj in smonths:
idx += 30
month_idx.append(idx)
elif jj == 1:
idx += 28
month_idx.append(idx)
fig = plt.figure(figsize=(10,4), dpi=300)
plt.plot(month_idx,bcmonthly,'r')
plt.plot(days, dailyavg, ':', linewidth=1)
plt.xlim([-1,366])
plt.title("Monthly and Daily Averages")
plt.xticks(month_idx, months, rotation=45)
plt.show()
Alternatively, you can use the object-oriented approach of ax.plot()
, but that requires you to specify the tick labels and positions separately,
import matplotlib.pyplot as plt
import numpy as np
bcmonthly = np.random.rand(12)
dailyavg = np.random.rand(365)
days = np.linspace(0, 364, 365)
months = ['January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September',
'October', 'November', 'December']
lmonths = [0, 2, 4, 6, 7, 9, 11]
smonths = [3, 5, 8, 10]
month_idx = list()
idx = -15 # Puts the month avg and label in the center of the month
for jj in range(len(months)):
if jj in lmonths:
idx += 31
month_idx.append(idx)
elif jj in smonths:
idx += 30
month_idx.append(idx)
elif jj == 1:
idx += 28
month_idx.append(idx)
fig = plt.figure(figsize=(10,4), dpi=300)
ax1 = fig.add_subplot(111)
ax1.plot(month_idx,bcmonthly,'r')
ax2 = ax1.twinx()
ax2.plot(days, dailyavg, ':', linewidth=1)
plt.xlim([-1,366])
plt.title("Monthly and Daily Averages")
ax1.set_xticklabels(months, rotation=45)
ax1.set_xticks(month_idx)
plt.show()
Upvotes: 1
Reputation: 933
When plotting months
vs dailyavg
, you need to extend months
to have length 364 -- Matplotlib cannot decide for you which of the 12 x-values in months
to assign each of the 364 daily averages to, but you can supply that information yourself by making a list of x-values of the appropriate length.
So, in this case, it seems like that would mean making a list containing "January"
31 times, then "February"
28 times, and so on... until you hit length 364 (depending on which day is missing?)
Upvotes: 0