python plot multiple bar ranges with dates - pandas

I have this two dataframe:
x1=[{"dates":'2018-01-31',"rev":-2},
{"dates":'2018-02-28',"rev":-5},
{"dates":'2018-03-31',"rev":-7},
{"dates":'2018-04-30',"rev":-8},
{"dates":'2018-05-31',"rev":-9},
{"dates":'2018-06-30',"rev":-2},
{"dates":'2018-07-31',"rev":1},
{"dates":'2018-08-31',"rev":2},
{"dates":'2018-09-30',"rev":3},
{"dates":'2018-10-31',"rev":4},
{"dates":'2018-11-30',"rev":4},
{"dates":'2018-12-31',"rev":5}]
x2=[{"dates":'2018-01-31',"rev":-5},
{"dates":'2018-02-28',"rev":-9},
{"dates":'2018-03-31',"rev":-9},
{"dates":'2018-04-30',"rev":-6},
{"dates":'2018-05-31',"rev":-1},
{"dates":'2018-06-30',"rev":-2},
{"dates":'2018-07-31',"rev":-14},
{"dates":'2018-08-31',"rev":2},
{"dates":'2018-09-30',"rev":3},
{"dates":'2018-10-31',"rev":4},
{"dates":'2018-11-30',"rev":-4},
{"dates":'2018-12-31',"rev":5}]
df1=pd.DataFrame(x1)
df1["dates"]=pd.to_datetime(df1.dates)
df2=pd.DataFrame(x2)
df2["dates"]=pd.to_datetime(df2.dates)
(Thanks Flavio Moraes
)
I would like to plot then as a bar plot. The matplotlib guide suggests to do something like the following:
width = 0.35
fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, y1, width, label='y1')
rects2 = ax.bar(x + width/2, y2, width, label='y2')
However, this seems to not working with dates. Indeed I have tried:
ax = plt.axes()
widthb = 10
rects1 = ax.bar(df1.dates - widthb/2, df1.rev,color='blue', width=widthb)
rects2 = ax.bar(df2.dates + widthb/2, df2.rev,color='red', width=widthb)
ax.xaxis_date()
As expected, I get the following error:
unsupported operand type(s) for -: 'DatetimeIndex' and 'float'
Do you have any suggestion to overcome this problem and simultaneously to have a beautiful plot?
Thanks

Let's try merge and plot:
ax = df1.merge(df2, on='dates', how='outer').plot.bar(x='dates')
# other format with `ax`
ax.xaxis_date()
Output:

Related

Matplotlib doesn't show both datasets points on the figure when I want to create scatter plot with

I'm sure that I've done all things right but in the end the result I got is a sccatter plot that only shows the second datasets data.
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.scatter(train["ENGINESIZE"], train["CO2EMISSIONS"], color = "green")
ax1.scatter(test["ENGINESIZE"], test["CO2EMISSIONS"], color = "red")
plt.xlabel("Engine Size")
plt.ylabel("Emission")
plt.show()
Here You can see what's going on in my output in link below.
It shows only red data(test data) in the output.
Where is the "output link below", please? For now I can only imagine what you are describing.
Also it helps if both plots have the same axis. That is, both have the same x-axis and then they can vary on their y-axis.
If so:
fig, ax = plt.subplots()
df.plot(kind = 'scatter', x= train["ENGINESIZE"], y = train["CO2EMISSIONS"], color = {'g'}, ax = ax)
df.plot(kind = 'scatter', x= test["ENGINESIZE"], y = test["CO2EMISSIONS"], color = {'r'}, ax = ax)
plt.xlabel()

How do I invert matplotlib bars at a specific point instead of when negative?

I'd like to invert the bars in this diagram when they are below 1, not when they are negative. Additionally I'd like to have even spacing between the ticks/steps on the y-axis
Here is my current code
import matplotlib.pyplot as plt
import numpy as np
labels = ['A','B','C']
Vals1 = [28.3232, 12.232, 9.6132]
Vals2 = [0.00456, 17.868, 13.453]
Vals3 = [0.0032, 1.234, 0.08214]
x = np.arange(len(labels))
width = 0.2
fig, ax = plt.subplots()
rects1 = ax.bar(x - width, Vals1, width, label='V1')
rects2 = ax.bar(x, Vals2, width, label='V2')
rects3 = ax.bar(x + width, Vals3, width, label='V3')
ax.set_xticks(x)
ax.set_xticklabels(labels)
plt.xticks(rotation=90)
ax.legend()
yScale = [0.0019531,0.0039063,0.0078125,0.015625,0.03125,0.0625,0.125,0.25,0.5,1,2,4,8,16,32]
ax.set_yticks(yScale)
plt.show()
I believe I've stumbled upon the answer, here it is for anyone else looking for the solution. Add the argument bottom='1' to ax.bar instantiation, and then flip the values in the array.
for i in range(len(Vals1)):
Vals1[i] = (1 - Vals1[i]) * -1
As you mentioned, the key is the bottom param of Axes.bar:
bottom (default: 0): The y coordinate(s) of the bars bases.
But beyond that, you can simplify your plotting code using pandas:
Put your data into a DataFrame:
import pandas as pd
df = pd.DataFrame({'V1': Vals1, 'V2': Vals2, 'V3': Vals3}, index=labels)
# V1 V2 V3
# A 28.3232 0.00456 0.00320
# B 12.2320 17.86800 1.23400
# C 9.6132 13.45300 0.08214
Then use DataFrame.sub to subtract the offset and DataFrame.plot.bar with the bottom param:
bottom = 1
ax = df.sub(bottom).plot.bar(bottom=bottom)

y and x axis subplots matplotlib

A quite basic question about ticks' labels for x and y-axis. According to this code
fig, axes = plt.subplots(6,12, figsize=(50, 24), constrained_layout=True, sharex=True , sharey=True)
fig.subplots_adjust(hspace = .5, wspace=.5)
custom_xlim = (-1, 1)
custom_ylim = (-0.2,0.2)
for i in range(72):
x_data = ctheta[i]
y_data = phi[i]
y_err = err_phi[i]
ax = fig.add_subplot(6, 12, i+1)
ax.plot(x_data_new, bspl(x_data_new))
ax.axis('off')
ax.errorbar(x_data,y_data, yerr=y_err, fmt="o")
ax.set_xlim(custom_xlim)
ax.set_ylim(custom_ylim)
I get the following output:
With y labels for plots on the first column and x labels for theone along the last line, although I call them off.
Any idea?
As #BigBen wrote in their comment, your issue is caused by you adding axes to your figure twice, once via fig, axes = plt.subplots() and then once again within your loop via fig.add_subplot(). As a result, the first set of axes is still visible even after you applied .axis('off') to the second set.
Instead of the latter, you could change your loop to:
for i in range(6):
for j in range(12):
ax = axes[i,j] # these are the axes created via plt.subplots(6,12,...)
ax.axis('off')
# … your other code here

How to stack the graphs in such a way that the share a common scale along x-axis

The following code is for generating the 3 subplots. And on all the 3 subplots scale is mentioned. I want to stack them in such a way that x-axis and y-axis scale appear once like this. Can I get this plot with plt.subplot() or fig.add_axes is compulsory for this? I actually want to do this with subplots because in fig.add_subplot I havve to specify the width and height of each plot that I don't want.
`fig,axes = plt.figure(nrow=3, ncolmn=1)
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)
ind1 =[1,2,3]
ind2 = [4,5,6]
for i in range(len(3)):
data1=np.load(..)
data2=np.load(..)
axes[i].plot(data1, data2)`
Here is one solution using subplots_adjust where you put the space between two plots to 0 using hspace. Also, use sharex=True to have a shared x-axis
fig, axes = plt.subplots(nrows=3, ncols=1,sharex=True)
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
for i, ax in enumerate(axes.ravel()): # or axes.flatten() or axes.flat
ax.plot(x, y, label='File %d' %i)
ax.legend()
fig.text(0.5, 0.01, 'X-label', ha='center')
fig.text(0.01, 0.5, 'Y-label', va='center', rotation='vertical')
plt.tight_layout() # To get a better spacing between the subplots
plt.subplots_adjust(hspace=.0)

How to print values/scale on the y-axis of a bar plot

This is what I have done so far. My problen, however, is that I can't print the values/scale on the y-axis of a bar plot? Any ideas? What other stylings whould I add?
import seaborn as sb
from matplotlib import pyplot
%matplotlib inline
sb.axes_style("white")
sb.set_style("ticks")
sb.set_context("talk")
x1 = np.array(['U', 'G'])
x2 = np.array(['H', 'W'])
f, (ax1, ax2) = pyplot.subplots(1, 2, figsize=(12, 6))
y1 = np.array([831824, 3306662])
y2 = np.array([1798043, 1508619])
sb.barplot(x1, y1, ci=None, palette="Blues", hline=.0001, ax=ax1)
sb.barplot(x1, y2, ci=None, palette="Reds", hline=.0001, ax=ax2)
ax1.set_ylabel("Occurences")
ax1.set_xlabel("Totals")
ax2.set_ylabel("Occurences")
ax2.set_xlabel("Types")
sb.despine(bottom=True)
pyplot.setp(f.axes, yticks=[])
pyplot.tight_layout(h_pad=3)
sb.despine()
Based on #john-cipponeri's answer:
Using functions operating on axes called using pyplot.* only operate on the last opened axis, in your case ax2, which is the the right plot. Use the axis instance to take it effect where you want. Replace tour last block of your code with this one and I hope it corresponds to your expected plot:
ax1.grid(axis='y', linestyle='-')
ax2.grid(axis='y', linestyle='-')
pyplot.tight_layout(h_pad=3)
sb.despine()
You can try a line style.
pyplot.grid(axis='y', linestyle='-')