I have a requirement to add subplots with two column and with multiple rows. The rows will not be fixed but for one column I want to create seaborn line plot from one data set and for second column i want to create seaborn line plot for another data set.
I have tried the following but not working.
tips = sns.load_dataset("tips")
dataset2=tips
days = list(tips.drop_duplicates('day')['day'])
ggpec = gridspec.GridSpec(len(days ), 2)
axs = []
for i,j in zip(days,range(1,len(days)+1)):
fig = plt.figure(figsize=(20,4),dpi=200)
palette = sns.color_palette("magma", 2)
chart = sns.lineplot(x="time", y="total_bill",
hue="sex",style='sex',
palette=palette, data=tips[tips['day']==i])
chart.set_xticklabels(
chart.get_xticklabels(),
rotation=90,
minor=True,
verticalalignment=True,
horizontalalignment='right',
fontweight='light',
fontsize='large'
)
plt.title("Title 1",fontsize=18, fontweight='bold')
fig2 = plt.figure(figsize=(20,5),dpi=200)
palette = sns.color_palette("magma", 2)
chart = sns.lineplot(x="time", y="total_bill",
hue="sex",style='sex',
palette=palette, data=dataset2[dataset2['day']==i])
chart.set_xticklabels(
chart.get_xticklabels(),
rotation=90,
minor=True,
verticalalignment=True,
horizontalalignment='right',
fontweight='light',
fontsize='large'
)
plt.title("Title 2",fontsize=18, fontweight='bold')
plt.show()
for creating multiple plots with 2 columns and multiple rows, you can use subplot. Where in you define the number of rows, columns and the subplot to activate at present.
import matplotlib.pyplot as plt
plt.subplot(3, 2, 1) # Define 3 rows, 2 column, Activate subplot 1.
plt.plot([1, 2, 3, 4, 5, 6, 7], [7, 8, 6, 5, 2, 2, 4], 'b*-', label='Plot 1')
plt.subplot(3, 2, 2) # 3 rows, 2 column, Activate subplot 2.
# plot some data here
plt.plot([1, 2, 3, 4, 5, 6, 7], [7, 8, 6, 5, 2, 2, 4], 'b*-', label='Plot 2')
plt.subplot(3, 2, 3) # 3 rows, 2 column, Activate subplot 3.
# plot some data here
plt.plot([1, 2, 3, 4, 5, 6, 7], [7, 8, 6, 5, 2, 2, 4], 'b*-', label='Plot 3')
# to Prevent subplots overlap
plt.tight_layout()
plt.show()
You can build upon this concept to draw you seaborn plots as well.
f, axes = plt.subplots(3,2) # Divide the plot into 3 rows, 2 columns
# Draw the plot in first row second column
sns.lineplot(xData, yData, data=dataSource, ax=axes[0][1])
Related
I would like to show in every bin of the histogram, the 3 bars separated, so that it does not overlap. My code is this:
face = io.imread('images/face.png')
red_chanel = face[:,:,0]
green_chanel = face[:,:,1]
blue_chanel = face[:,:,2]
red_chanel = red_chanel.astype('float')
green_chanel = green_chanel.astype('float')
blue_chanel = blue_chanel.astype('float')
face = face.astype('float')
fig, ax1 = plt.subplots(ncols = 1, figsize = (20, 5))
hstred=exposure.histogram(red_chanel, nbins=28)
hstgreen=exposure.histogram(green_chanel, nbins=28)
hstblue=exposure.histogram(blue_chanel, nbins=28)
ax1.bar(list(range(28)), hstred[0], align='edge')
ax1.bar(list(range(28)), hstgreen[0], align='edge')
ax1.bar(list(range(28)), hstblue[0], align='edge')
plt.show()
How can I separate the bars?
I think you can shift the x-axis for 2nd and 3rd barplot and play with bar width a little. In the end, change the xticks.
import numpy as np
ax1.bar(np.arange(28), hstred[0], align='edge', width=0.3)
#shifting the xaxis
ax1.bar(np.arange(28)+0.3, hstgreen[0], align='edge', width=0.3)
ax1.bar(np.arange(28)+0.6, hstblue[0], align='edge', width=0.3)
plt.xticks(np.arange(0,28)+0.3, np.arange(0,28)) #resetting the ticks
Here is an example:
x1 = [1, 2, 3, 4, 5]
y1 = [1, 2, 3, 5, 6]
y2 = [4, 4, 2, 2, 2]
y3 = [3, 4, 6, 7, 8]
fig,ax = plt.subplots()
ax.bar(x1,y1,width=0.3)
ax.bar(np.array(x1)+0.3,y2,width=0.3)
ax.bar(np.array(x1)+0.6,y3,width=0.3)
plt.xticks(np.arange(0,6)+0.3, np.arange(0,6))
plt.show()
Output:
I'm trying to plot a delaunay triangulation from a pandas df. I'm hoping to group the points by Time. At present, I'm getting an error when attempting to plot the point from the first time point.
QhullError: QH6214 qhull input error: not enough points(2) to construct initial simplex (need 6)
While executing: | qhull d Q12 Qt Qc Qz Qbb
Options selected for Qhull 2019.1.r 2019/06/21:
run-id 768388270 delaunay Q12-allow-wide Qtriangulate Qcoplanar-keep
Qz-infinity-point Qbbound-last _pre-merge _zero-centrum Qinterior-keep
_maxoutside 0
It appears it's only passing those two arrays as a single points.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay
df = pd.DataFrame({
'Time' : [1,1,1,1,2,2,2,2],
'A_X' : [5, 5, 6, 6, 4, 3, 3, 4],
'A_Y' : [5, 6, 6, 5, 5, 6, 5, 6],
})
fig, ax = plt.subplots(figsize = (6,6))
ax.set_xlim(0,10)
ax.set_ylim(0,10)
ax.grid(False)
points_x1 = df.groupby("Time")["A_X"].agg(list).tolist()
points_y1 = df.groupby("Time")["A_Y"].agg(list).tolist()
points = list(zip(points_x1, points_y1))
tri = Delaunay(points[0])
#plot triangulation
plt.triplot(points[:,0], points[:,1], tri.simplices)
plt.plot(points[:,0], points[:,1], 'o')
You can take advantage of the apply method which allows to perform operation on Series.
def make_points(x):
return np.array(list(zip(x['A_X'], x['A_Y'])))
c = df.groupby("Time").apply(make_points)
Result is properly shaped array of points for each time bucket:
Time
1 [[5, 5], [5, 6], [6, 6], [6, 5]]
2 [[4, 5], [3, 6], [3, 5], [4, 6]]
dtype: object
Finally it suffices to compute the Delaunay triangulation for each time bucket and plot it:
fig, axe = plt.subplots()
for p in c:
tri = Delaunay(p)
axe.triplot(*p.T, tri.simplices)
You can even make it in a single call:
def make_triangulation(x):
return Delaunay(np.array(list(zip(x['A_X'], x['A_Y']))))
c = df.groupby("Time").apply(make_triangulation)
fig, axe = plt.subplots()
for tri in c:
axe.triplot(*tri.points.T, tri.simplices)
I can layover two curves in 1 plot like so
X = np.array([1, 5, 8])
y = np.array([2, 10, 3])
x_max = np.array([5])
y_max = np.array([10])
fig, ax = plt.subplots(figsize=(8,6));
ax.plot(X, y, 'k--', label="savitzky")
ax.scatter(x_max, y_max, s=200, c='k', marker='*');
Then I will get the following:
Lets say I have a data frame and I want to plot all of its columns at once. I can do that like so:
df_2 = pd.DataFrame(data = {'col_1':np.array([2, 10, 3]), 'col_2':np.array([3, 4, 7])},
index = np.array([1, 5, 8]))
df_2.plot()
to get:
My question is how can I combine these two so I can plot the whole dataframe at once
and then lay over my vectors of maximum points?(my real data frame is bigger than this, and so are the vectors of maximums)
Thanks
The following is one way to do it:
Create an axis object ax
Plot the DataFrame on this axis
Get the maximum element and the corresponding index for each column
Make a scatter plot on the same axis ax
fig, ax = plt.subplots()
df_2 = pd.DataFrame(data = {'col_1':np.array([2, 10, 3]),
'col_2':np.array([3, 4, 7])},
index = np.array([1, 5, 8]))
df_2.plot(ax=ax) # Plot the DataFrame on ax object
max_points = [(df_2[col].idxmax(), df_2[col].max()) for col in df_2.columns]
ax.plot(*zip(*max_points), 'b*', ms=10) # Unpack the list of (x, y) tuples
ax.set_xlim(None, 8.2)
You can do it like this:
Here I have assigned the axis object given by the df_2.plot to ax and plotted the further graph on it (ax)
X = np.array([1, 5, 8])
y = np.array([2, 10, 3])
x_max = np.array([5])
y_max = np.array([10])
df_2 = pd.DataFrame(data = {'col_1':np.array([2, 10, 3]), 'col_2':np.array([3, 4, 7])}, index = np.array([1, 5, 8]))
ax=df_2.plot(figsize=(8,6))
ax.plot(X, y, 'k--', label="savitzky")
ax.scatter(x_max, y_max, s=200, c='k', marker='*');
plt.show()
I've got 5 classes and some features that I want to plot. This is the code
x_pts = X_test.iloc[:,col_1]
y_pts = X_test.iloc[:,col_2]
color_seq = y_test
plt.scatter(x_pts, y_pts, c=color_seq, cmap='viridis')
plt.xlabel(X_test.columns[col_1])
plt.ylabel(X_test.columns[col_2])
plt.show()
and this results in the following image
I now want a legend for each color (e.g. yellow = 'class a' , blue = 'class b', ...)
The only documentation I can find is of people plotting each color differently, which is quite hard in my specific case. Isn't there a simple way to display a legend like the example here
Hope this helps:
x = [1, 3, 4, 6, 7, 9]
y = [0, 0, 5, 8, 8, 8]
labels = ['A', 'B', 'C']
colors = [0, 0, 1, 2, 2, 2]
scatter = plt.scatter(x, y,c=colors, cmap='viridis')
plt.legend(handles=scatter.legend_elements()[0], labels=labels)
plt.show()
Output:
i would like to multiple stacked bar in the same plot. This is my code:
file_to_plot = file_to_plot.set_index(['user'])
fig, ax = plt.subplots()
fontP = FontProperties()
fontP.set_size('small')
file_to_plot[[" mean_accuracy_all_classes_normal", " delta_all_classes"]].plot(ax=ax, kind='bar', color= ['g', 'r'], width = 0.65, align="center", stacked=True)
file_to_plot[[" mean_accuracy_user_classes_normal", " delta_user_classes"]].plot(ax=ax, kind='bar', color=['y', 'b'], width=0.65, align="center", stacked = True)
lgd = ax.legend(['Tutte le classi (normale)', 'Tutte le classi (incrementale)', 'Classi utente (normale)', 'Classi utente (incrementale)'], prop=fontP, loc=9, bbox_to_anchor=(0.5, -0.15), ncol=4,borderaxespad=0.)
ax.set_ylabel('% Accuratezza')
ax.set_xlabel('Utenti')
This is the results:
The second plot overwhelms me when I want to plot them together. How can I do?
This should work the way you want:
import pandas as pd
df = pd.DataFrame(dict(
A=[1, 2, 3, 4],
B=[2, 3, 4, 5],
C=[3, 4, 5, 6],
D=[4, 5, 6, 7]))
import matplotlib.pyplot as plt
%matplotlib inline
fig = plt.figure(figsize=(20, 10))
ab_bar_list = [plt.bar([0, 1, 2, 3], df.B, align='edge', width= 0.2),
plt.bar([0, 1, 2, 3], df.A, align='edge', width= 0.2)]
cd_bar_list = [plt.bar([0, 1, 2, 3], df.D, align='edge',width= -0.2),
plt.bar([0, 1, 2, 3], df.C, align='edge',width= -0.2)]
Just keep in mind, the width value for one group must be positive, and negative for the second one. Use align by edge as well.
You have to place the bar with the biggest values before the bar with the lowest values, and if you want the bars to appear stacked above one another rather than one in front of another, change df.B and df.D to df.B + df.A and df.D + df.C, respectively. If there's no apparent or consisting pattern, use the align by edge and width method with the one suggested by #piRSquared.
Another alternative would be to access each value from a green bar and compare it to the corresponding value from the red bar, and plot accordingly (too much unnecessary work in this one).
I thought this would be straightforward. Hopefully someone else will chime in with a better solution. What I did was to take the diff's of the columns and run a stacked chart.
df = pd.DataFrame(dict(
A=[1, 2, 3, 4],
B=[2, 3, 4, 5],
C=[3, 4, 5, 6]
))
df.diff(axis=1).fillna(df).astype(df.dtypes).plot.bar(stacked=True)
For comparison
fig, axes = plt.subplots(1, 2, figsize=(10, 4), sharey=True)
df.plot.bar(ax=axes[0])
df.diff(axis=1).fillna(df).astype(df.dtypes).plot.bar(ax=axes[1], stacked=True)
there is in fact a direct way of stacking the bars via the bottom keyword
(if you plot a horizontal barplot with plt.barh use left instead of bottom)!
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame(dict(A=[1, 2, 3, 4], B=[2, 3, 4, 5], C=[3, 4, 5, 6]))
df2 = df / 2
f, ax = plt.subplots()
ax.bar(df.index, df.A, align='edge', width=0.2)
ax.bar(df.index, df.B, align='edge', width=0.2, bottom=df.A)
ax.bar(df.index, df.C, align='edge', width=0.2, bottom=df.A + df.B)
ax.bar(df2.index, df2.A, align='edge', width=-0.2)
ax.bar(df2.index, df2.B, align='edge', width=-0.2, bottom=df2.A)
ax.bar(df2.index, df2.C, align='edge', width=-0.2, bottom=df2.A + df2.B)
I used numpy to add the arrays together. Not sure if its exactly what you wanted, but its what I needed when I stumbled on this question. Thought it might help others.
import matplotlib.pyplot as plt
import numpy as np
dates = ['22/10/21', '23/10/21', '24/10/21', '25/10/21', '26/10/21']
z1 = np.array([20, 35, 30, 35, 27])
z2 = np.array([25, 32, 34, 20, 25])
z3 = np.array([20, 35, 30, 35, 27])
z4 = np.array([25, 32, 34, 20, 25])
z5 = np.array([20, 35, 30, 35, 27])
width = 0.35 # the width of the bars: can also be len(x) sequence
fig, ax = plt.subplots()
ax.bar(dates, z1, width, color='0.8', label='Z1')
ax.bar(dates, z2, width, color='b', label='Z2',bottom=z1)
ax.bar(dates, z3, width, color='g', label='Z3',bottom=z1 + z2)
ax.bar(dates, z4, width, color='tab:orange', label='Z4',bottom=z1 + z2 + z3)
ax.bar(dates, z5, width, color='r', bottom=z1 + z2 + z3 + z4,
label='Z5')
ax.set_ylabel('Time in HR Zones')
ax.set_title('HR Zones')
ax.legend()
plt.show()
Stacked Bar Graph