How to mirror the bars - pandas

I have two bars which I want to mirror. I have the following code
bar1 = df['nt'].value_counts().plot.barh()
bar2 = df1['nt'].value_counts().plot.barh()
bar1.set_xlim(bar1.get_xlim()[::-1])
# bar1.yaxis.tick_right()
But somehow not only the bar1 flips to the left(third line), but also the bar2. The same happening with the commented 4th line. Why is that? How to do it right then?

df...plot.barh()doesn't return bars nor a barplot. It returns theaxwhich indicates the subplot where the barplot was added. As both barplots are created onto the same subplot,set_xlim` etc. will act on that same subplot. This blogpost might be helpful.
To get two barplots, one from the left and one from the right, you could create a "twin" y -axis and then drawing one bar plot using the lower x-axis and the other user the upper x-axis. To make things clearer, the tick labels can be colored the same as the bars. To avoid overlapping bars, the x limits should be at least the maximum of the sum of the two value_counts.
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
df = pd.DataFrame({'nt': np.random.choice([*'abcdefhij'], 50)})
df1 = pd.DataFrame({'nt': np.random.choice([*'abcdefhij'], 50)})
max_sum_value_counts = df.append(df1).value_counts().max()
fig, ax = plt.subplots(figsize=(12, 5))
df['nt'].value_counts(sort=False).sort_index().plot.barh(ax=ax, color='purple')
ax.set_xlim(0, max_sum_value_counts + 1)
ax.tick_params(labelcolor='purple')
ax1 = ax.twiny()
df1['nt'].value_counts(sort=False).sort_index().plot.barh(ax=ax1, color='crimson')
ax1.set_xlim(max_sum_value_counts + 1, 0)
ax1.tick_params(labelcolor='crimson', labelright=True, labelleft=False)
ax1.invert_yaxis()
plt.show()

Related

overlapping two plots in matplotlib

I've two plots generated using matplotlib. The first represents my backround and the second a group of points which I want to show. Is there a way to overlap the two plots?
background:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize = (10,10))
grid_duomo = gpd.read_file('/content/Griglia_2m-SS.shp')
grid_duomo.to_crs(epsg=32632).plot(ax=ax, color='lightgrey')
points:
fig = plt.figure(figsize=(10, 10))
ids = traj_collection_df_new_app['id'].unique()
for id_ in ids:
self_id = traj_collection_df_new_app[traj_collection_df_new_app['id'] == id_]
plt.plot(
self_id['lon'],
self_id['lat'],
# markers= 'o',
# markersize=12
)
plt.plot() will always take the most recent axis found by matplotlib and use it for plotting.
Its practically the same as plt.gca().plot() where plt.gca() stands for "get current axis".
To get full control over which axis is used, you should do something like this:
(the zorder argument is used to set the "vertical stacking" of the artists, e.g. zorder=2 will be plotted on top of zorder=1)
f = plt.figure() # create a figure
ax = f.add_subplot( ... ) # create an axis in the figure f
ax.plot(..., zorder=0)
grid_duomo.plot(ax=ax, ..., zorder=1)
# you can then continue to add more axes to the same figure using
# f.add_subplot() or f.add_axes()
(if this is unclear, maybe check the quick_start guide of matplotlib? )

Combine two matplotlib Figures, side by side, high quality

I produced two matplotlib Figures, at size of 1000x1000.
Each of the figures is 4x4 subplots based figure.
I want one figure at size of 1000x2000 (width is 2000).
fig1
<Figure size 1000x1000 with 4 Axes>
fig2
<Figure size 1000x1000 with 4 Axes>
Now I want to combine them together.
I've searched many references:
How to make two plots side-by-side using Python?
Plotting two figures side by side
Adding figures to subplots in Matplotlib
They are not relevant because mostly they suggest to change the way the initial plots were created. I don't want to change it - I want to use the Figure as is.
I just need to place Fig1 to the left of Fig2. Not changing the way Fig1 or Fig2 were created.
I also tried using PIL method: https://note.nkmk.me/en/python-pillow-concat-images/
However it was lower quality
You can render your figures to arrays using the agg backend.
Then concat the arrays side by side and switch back to your normal backend to show the result:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
backend = mpl.get_backend()
mpl.use('agg')
dpi = 100
fig1,_ = plt.subplots(2,2, figsize=(1000/dpi, 1000/dpi), dpi=dpi)
fig1.suptitle('Figure 1')
fig2,_ = plt.subplots(2,2, figsize=(1000/dpi, 1000/dpi), dpi=dpi)
fig2.suptitle('Figure 2')
c1 = fig1.canvas
c2 = fig2.canvas
c1.draw()
c2.draw()
a1 = np.array(c1.buffer_rgba())
a2 = np.array(c2.buffer_rgba())
a = np.hstack((a1,a2))
mpl.use(backend)
fig,ax = plt.subplots(figsize=(2000/dpi, 1000/dpi), dpi=dpi)
fig.subplots_adjust(0, 0, 1, 1)
ax.set_axis_off()
ax.matshow(a)
Not directly merging two seperate figures, but I succeeded achieving the final goal by using this reference:
https://matplotlib.org/devdocs/gallery/subplots_axes_and_figures/subfigures.html
That's the code I needed:
fig = plt.figure(constrained_layout=True, figsize=(20, 11))
titles_size = 25
labels_size = 18
subfigs = fig.subfigures(1, 2, wspace=0.02)
subfigs[0].suptitle('Title 1', fontsize=titles_size)
subfigs[1].suptitle('Title 2', fontsize=titles_size)
axsLeft = subfigs[0].subplots(2, 2)
axsRight = subfigs[1].subplots(2, 2)
for ax_idx, ax in enumerate(axsLeft.reshape(-1)):
ax.grid(False)
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
for ax_idx, ax in enumerate(axsRight.reshape(-1)):
ax.grid(False)
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.show()

Multiple different kinds of plots on a single figure and save it to a video

I am trying to plot multiple different plots on a single matplotlib figure with in a for loop. At the moment it is all good in matlab as shown in the picture below and then am able to save the figure as a video frame. Here is a link of a sample video generated in matlab for 10 frames
In python, tried it as below
import matplotlib.pyplot as plt
for frame in range(FrameStart,FrameEnd):#loop1
# data generation code within a for loop for n frames from source video
array1 = np.zeros((200, 3800))
array2 = np.zeros((19,2))
array3 = np.zeros((60,60))
for i in range(len(array2)):#loop2
#generate data for arrays 1 to 3 from the frame data
#end loop2
plt.subplot(6,1,1)
plt.imshow(DataArray,cmap='gray')
plt.subplot(6, 1, 2)
plt.bar(data2D[:,0], data2D[:,1])
plt.subplot(2, 2, 3)
plt.contourf(mapData)
# for fourth plot, use array2[3] and array2[5], plot it as shown and keep the\is #plot without erasing for next frame
not sure how to do the 4th axes with line plots. This needs to be there (done using hold on for this axis in matlab) for the entire sequence of frames processing in the for loop while the other 3 axes needs to be erased and updated with new data for each frame in the movie. The contour plot needs to be square all the time with color bar on the side. At the end of each frame processing, once all the axes are updated, it needs to be saved as a frame of a movie. Again this is easily done in matlab, but not sure in python.
Any suggestions
thanks
I guess you need something like this format.
I have used comments # in code to answer your queries. Please check the snippet
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(6,6))
ax1=fig.add_subplot(311) #3rows 1 column 1st plot
ax2=fig.add_subplot(312) #3rows 1 column 2nd plot
ax3=fig.add_subplot(325) #3rows 2 column 5th plot
ax4=fig.add_subplot(326) #3rows 2 column 6th plot
plt.show()
To turn off ticks you can use plt.axis('off'). I dont know how to interpolate your format so left it blank . You can adjust your figsize based on your requirements.
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(6,6)) #First is width Second is height
ax1=fig.add_subplot(311)
ax2=fig.add_subplot(312)
ax3=fig.add_subplot(325)
ax4=fig.add_subplot(326)
#Bar Plot
langs = ['C', 'C++', 'Java', 'Python', 'PHP']
students = [23,17,35,29,12]
ax2.bar(langs,students)
#Contour Plot
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
cp = ax3.contourf(X, Y, Z)
fig.colorbar(cp,ax=ax3) #Add a colorbar to a plot
#Multiple line plot
x = np.linspace(-1, 1, 50)
y1 = 2*x + 1
y2 = 2**x + 1
ax4.plot(x, y2)
ax4.plot(x, y1, color='red',linewidth=1.0)
plt.tight_layout() #Make sures plots dont overlap
plt.show()

how to combine two bar chart of two files in one diagram in matplotlib pandas

I have two dataframe with the same columns but different content.
I have plotted dffinal data frame. now I want to plot another dataframe dffinal_no on the same diagram to be comparable.
for example one bar chart in blue colour, and the same bar chart with another colour just differentiating in y-axis.
This is part of the code in which I have plotted the first data frame.
dffinal = df[['6month','final-formula','numPatients6month']].drop_duplicates().sort_values(['6month'])
ax=dffinal.plot(kind='bar',x='6month', y='final-formula')
import matplotlib.pyplot as plt
ax2 = ax.twinx()
dffinal.plot(ax=ax2,x='6month', y='numPatients6month')
plt.show()
Now imagine I have another dffinal_no data frame with the same columns, how can I plot it in the same diagram?
This is my first diagram which I plotted, I want the other bar chart on this diagram with another color.
so the answer of #Mohamed Thasin ah is somehow what I want, except that the right y-axis is not correct.
I want both data frame be based on (6month, final-formula) but the right y-axis is just showing number of patients, as an information for the user.
Actually, I DO NOT want the first df based on final-fomula and the second df be based on NumberPatients.
Update1 jast as a refrence how it looks like my data frame
dffinal = df[['6month','final-formula','numPatients6month']].drop_duplicates().sort_values(['6month'])
nocidffinal = nocidf[['6month','final-formula','numPatients6month']].drop_duplicates().sort_values(['6month'])
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_ylabel('final-formula')
ax2.set_ylabel('numPatients6month')
width=0.4
nocidffinal=nocidffinal.set_index('6month').sort_index()
dffinal=dffinal.set_index('6month').sort_index()
nocidffinal['final-formula'].plot(kind='bar',color='green',ax=ax1,width=width,position=0)
dffinal['numPatients6month'].plot(kind='bar',color='red',ax=ax2,width=width,position=1)
dffinal content
,6month,final-formula,numPatients6month
166047.0,1,7.794117647058823,680
82972.0,2,5.720823798627003,437
107227.0,3,5.734767025089606,558
111330.0,4,4.838709677419355,434
95591.0,5,3.3707865168539324,534
95809.0,6,3.611738148984198,443
98662.0,7,3.5523978685612785,563
192668.0,8,2.9978586723768736,467
89460.0,9,0.9708737864077669,515
192585.0,10,2.1653543307086616,508
184325.0,11,1.727447216890595,521
85068.0,12,1.0438413361169103,479
nocidffinal
,6month,final-formula,numPatients6month
137797.0,1,3.5934291581108826,974
267492.0,2,2.1705426356589146,645
269542.0,3,2.2106631989596877,769
271950.0,4,2.0,650
276638.0,5,1.5587529976019185,834
187719.0,6,1.9461077844311379,668
218512.0,7,1.1406844106463878,789
199830.0,8,0.8862629246676514,677
269469.0,9,0.3807106598984772,788
293390.0,10,0.9668508287292817,724
254783.0,11,1.2195121951219512,738
300974.0,12,0.9695290858725761,722
to compare two data frame result with bar plot one way you could try is concatenating two data frames and adding hue.
For example consider below df it contains same x and y columns in both df's and wanna compare this values. to achieve this simply add hue column for each df with differentiating constant like below.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
df1=pd.DataFrame({'x':[1,2,3,4,5],'y':[10,2,454,121,34]})
df2=pd.DataFrame({'x':[4,1,2,5,3],'y':[54,12,65,12,8]})
df1['hue']=1
df2['hue']=2
res=pd.concat([df1,df2])
sns.barplot(x='x',y='y',data=res,hue='hue')
plt.show()
The result should looks like below:
To get two y-axis try this method,
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_ylabel('final-formula')
ax2.set_ylabel('numPatients6month')
width=0.4
df1=df1.set_index('x').sort_index()
df2=df2.set_index('x').sort_index()
df1['y'].plot(kind='bar',color='blue',ax=ax1,width=width,position=1)
df2['y'].plot(kind='bar',color='green',ax=ax2,width=width,position=0)
plt.show()
with actual input:
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_ylabel('final-formula')
ax2.set_ylabel('numPatients6month')
width=0.4
df1=df1.set_index('6month').sort_index()
df2=df2.set_index('6month').sort_index()
df1['final-formula'].plot(kind='bar',color='blue',ax=ax1,width=width,position=1)
df2['numPatients6month'].plot(kind='bar',color='green',ax=ax2,width=width,position=0)
plt.show()

how to plot 2 histograms side by side?

I have 2 dataframes. I want to plot a histogram based on a column 'rate' for each, side by side. How to do it?
I tried this:
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
dflux.hist('rate' , bins=100)
plt.subplot(1,2,2)
dflux2.hist('rate' , bins=100)
plt.tight_layout()
plt.show()
It did not have the desired effect. It showed two blank charts then one populated chart.
Use subplots to define a figure with two axes. Then specify the axis to plot to within hist using the ax parameter.
fig, axes = plt.subplots(1, 2)
dflux.hist('rate', bins=100, ax=axes[0])
dflux2.hist('rate', bins=100, ax=axes[1])
Demo
dflux = pd.DataFrame(dict(rate=np.random.randn(10000)))
dflux2 = pd.DataFrame(dict(rate=np.random.randn(10000)))
fig, axes = plt.subplots(1, 2)
dflux.hist('rate', bins=100, ax=axes[0])
dflux2.hist('rate', bins=100, ax=axes[1])