I use Seaborn/Matplotlib to display different outputs (time and distance for example) for different parameters. I would like to associate the two outputs on the same plot, thus I use seaborn's satplot and barplot.
My problem is I don't get the expected display. The graph is here but some noisy extra axis appear.
I'm running the following code
ax = plt.subplot(311)
ax2 = ax.twinx()
data = sns.load_dataset("tips")
sns.barplot(ax=ax, x="day",y="total_bill", hue="size" , data=data, ci=None)
ax.set_yscale("log")
sns.catplot(data=data, x="day", y="tip", ax=ax2, hue="size", kind="swarm", palette="bright")
And I have the following result :
Could you help me to remove this extra axis ? It is especially inconvenient when having multiple subplots.
The extra axis you see is the one returned by the catplot. To get rid of it, you can add the following line after the sns.catplot(...) where the index 2 refers to the count of the figure.
plt.close(2)
To test that, if you use plt.close(1), it will remove the main figure containing bar chart
The extra axes you see is the catplot you create. catplot is a figure-level function (i.e. it creates its own figure); and hence does not really have an ax argument. One could see it as bug that it still allows for it. What you would probably like to do is to create a sns.swarmplot instead, which does have the ax argument.
Related
How can I use the lineplot plotting function in seaborn to create a plot with no lines connecting between the points. I know the function is called lineplot, but it has the useful feature of merging all datapoints with the same x value and plotting a single mean and confidence interval.
tips = sns.load_dataset('tips')
sns.lineplot(x='size', y='total_bill', data=tips, marker='o', err_style='bars')
How do I plot without the line? I'm not sure of a better way to phrase my question. How can I plot points only? Lineless lineplot?
I know that seaborn has a pointplot function, but that is for categorical data. In some cases, my x-values are continuous values, so pointplot would not work.
I realize one could get into the matplotlib figure artists and delete the line, but that gets more complicated as the amount of stuff on the plot increases. I was wondering if there are some sort of arguments that can be passed to the lineplot function.
To get error bars without the connecting lines, you can set the linestyle parameter to '':
import seaborn as sns
tips = sns.load_dataset('tips')
sns.lineplot(x='size', y='total_bill', data=tips, marker='o', linestyle='', err_style='bars')
Other types of linestyle could also be interesting, for example "a loosely dotted line": sns.lineplot(..., linestyle=(0, (1, 10)))
I recommend setting join=False.
For me only join = True works.
sns.pointplot(data=df, x = "x_attribute", y = "y_attribute", ci= 95, join=False)
I am plotting two dataframes in the same chart: the USDEUR exchange rate and the 3-day moving average.
df.plot(ax=ax, linewidth=1)
rolling_mean.plot(ax=ax, linewidth=1)
Both dataframes are labelled "Value" so I would like to customize that:
I tried passing the label option but that didn't work, as it seems that this option is exclusive to matplotlib.axes.Axes.plot and not to pandas.DataFrame.plot. So I tried using axes instead, and passing each label:
ax.plot(df, linewidth=1, label='FRED/DEXUSEU')
ax.plot(rolling_mean, linewidth=1, label='3-day SMA')
However now the legend is not showing up at all unless I explicitly call ax.legend() afterwards.
Is it possible to plot the dataframes while passing custom labels without the need of an additional explicit call?
When setting a label using df.plot() you have to specifiy the data which is being plotted:
fig, (ax1, ax2) = plt.subplots(1,2)
df = pd.DataFrame({'Value':np.random.randn(10)})
df2 = pd.DataFrame({'Value':np.random.randn(10)})
df.plot(label="Test",ax=ax1)
df2.plot(ax=ax1)
df.plot(y="Value", label="Test",ax=ax2)
df2.plot(y="Value", ax=ax2)
ax1.set_title("Reproduce problem")
ax2.set_title("Possible solution")
plt.show()
Which gives:
Update: It appears that there is a difference between plotting a dataframe, and plotting a series. When plotting a dataframe, the labels are taken from the column names. However, when specifying y="Value" you are then plotting a series, which then actually uses the label argument.
I am trying to create a FacetGrid in Seaborn
My code is currently:
g = sns.FacetGrid(df_reduced, col="ActualExternal", margin_titles=True)
bins = np.linspace(0, 100, 20)
g.map(plt.hist, "ActualDepth", color="steelblue", bins=bins, width=4.5)
This gives my the Figure
Now, instead of "ActualExternal =0.0" and "ActualExternal =1.0" I would like the titles "Internal" and "External"
And, instead of "ActualDepth" I would like the xlabel to say "Percentage Depth"
Finally, I would like to add a ylabel of "Number of Defects".
I've tried Googling and have tried a few things but so far no success. Please can you help me?
Thanks
Although you can iterate through the axes and set the titles individually using matplotlib commands, it is cleaner to use seaborn's built-in tools to control the title. For example:
# Add a column of appropriate labels
df_reduced['measure'] = df_reduced['ActualExternal'].replace({0: 'Internal',
1: 'External'}
g = sns.FacetGrid(df_reduced, col="measure", margin_titles=True)
g.map(plt.hist, "ActualDepth", color="steelblue", bins=bins, width=4.5)
# Adjust title and axis labels directly
g.set_titles("{col_name}") # use this argument literally
g.set_axis_labels(x_var="Percentage Depth", y_var="Number of Defects")
This has the benefit of not needing modification regardless of whether you have 1D or 2D facets.
You can access the axes of a FacetGrid (g = sns.FacetGrid(...)) via g.axes. With that you are free to use any matplotlib method you like to tweak the plot.
Change titles:
axes = g.axes.flatten()
axes[0].set_title("Internal")
axes[1].set_title("External")
Change labels:
axes = g.axes.flatten()
axes[0].set_ylabel("Number of Defects")
for ax in axes:
ax.set_xlabel("Percentage Depth")
Note that I prefer those above the FacetGrid's internal g.set_axis_labels and set_titles methods, because it makes it more obvious which axes is to be labelled.
The easiest way to set multiple titles would be:
titles = ['Internal','External']
for ax,title in zip(g.axes.flatten(),titles):
ax.set_title(title )
I am trying to create a FacetGrid in Seaborn
My code is currently:
g = sns.FacetGrid(df_reduced, col="ActualExternal", margin_titles=True)
bins = np.linspace(0, 100, 20)
g.map(plt.hist, "ActualDepth", color="steelblue", bins=bins, width=4.5)
This gives my the Figure
Now, instead of "ActualExternal =0.0" and "ActualExternal =1.0" I would like the titles "Internal" and "External"
And, instead of "ActualDepth" I would like the xlabel to say "Percentage Depth"
Finally, I would like to add a ylabel of "Number of Defects".
I've tried Googling and have tried a few things but so far no success. Please can you help me?
Thanks
Although you can iterate through the axes and set the titles individually using matplotlib commands, it is cleaner to use seaborn's built-in tools to control the title. For example:
# Add a column of appropriate labels
df_reduced['measure'] = df_reduced['ActualExternal'].replace({0: 'Internal',
1: 'External'}
g = sns.FacetGrid(df_reduced, col="measure", margin_titles=True)
g.map(plt.hist, "ActualDepth", color="steelblue", bins=bins, width=4.5)
# Adjust title and axis labels directly
g.set_titles("{col_name}") # use this argument literally
g.set_axis_labels(x_var="Percentage Depth", y_var="Number of Defects")
This has the benefit of not needing modification regardless of whether you have 1D or 2D facets.
You can access the axes of a FacetGrid (g = sns.FacetGrid(...)) via g.axes. With that you are free to use any matplotlib method you like to tweak the plot.
Change titles:
axes = g.axes.flatten()
axes[0].set_title("Internal")
axes[1].set_title("External")
Change labels:
axes = g.axes.flatten()
axes[0].set_ylabel("Number of Defects")
for ax in axes:
ax.set_xlabel("Percentage Depth")
Note that I prefer those above the FacetGrid's internal g.set_axis_labels and set_titles methods, because it makes it more obvious which axes is to be labelled.
The easiest way to set multiple titles would be:
titles = ['Internal','External']
for ax,title in zip(g.axes.flatten(),titles):
ax.set_title(title )
I can clear the text of the xlabel in a Pandas plot with:
plt.xlabel("")
Instead, is it possible to hide the label?
May be something like .xaxis.label.set_visible(False).
From the Pandas docs -
The plot method on Series and DataFrame is just a simple wrapper around plt.plot():
This means that anything you can do with matplolib, you can do with a Pandas DataFrame plot.
pyplot has an axis() method that lets you set axis properties. Calling plt.axis('off') before calling plt.show() will turn off both axes.
df.plot()
plt.axis('off')
plt.show()
plt.close()
To control a single axis, you need to set its properties via the plot's Axes. For the x axis - (pyplot.axes().get_xaxis().....)
df.plot()
ax1 = plt.axes()
x_axis = ax1.axes.get_xaxis()
x_axis.set_visible(False)
plt.show()
plt.close()
Similarly to control an axis label, get the label and turn it off.
df.plot()
ax1 = plt.axes()
x_axis = ax1.axes.get_xaxis()
x_axis.set_label_text('foo')
x_label = x_axis.get_label()
##print isinstance(x_label, matplotlib.artist.Artist)
x_label.set_visible(False)
plt.show()
plt.close()
You can also get to the x axis like this
ax1 = plt.axes()
x_axis = ax1.xaxis
x_axis.set_label_text('foo')
x_axis.label.set_visible(False)
Or this
ax1 = plt.axes()
ax1.xaxis.set_label_text('foo')
ax1.xaxis.label.set_visible(False)
DataFrame.plot
returns a matplotlib.axes.Axes or numpy.ndarray of them
so you can get it/them when you call it.
axs = df.plot()
.set_visible() is an Artist method. The axes and their labels are Artists so they have Artist methods/attributes as well as their own. There are many ways to customize your plots. Sometimes you can find the feature you want browsing the Gallery and Examples
You can remove axis labels and ticks using xlabel= or ylabel= arguments in the plot() call. For example, to remove the xlabel, use xlabel='':
df.plot(xlabel='');
To remove the x-axis ticks, use xticks=[] (for y-axis ticks, use yticks=):
df.plot(xticks=[]);
To remove both:
df.plot(xticks=[], xlabel='');