It's easier to ask this with a figure. At the moment i obtain the following boxplot graph using matplotlib:
Is there a way to obtain a figure like that, but with each box in a position coherent with the corresponding x-axis number (like in a normal scatter plot, but with boxes instead of points)?
At the moment the numbers on the x-axis are added by means of the labels= argument.
You need to specify the positions argument to the boxplot constructor.
from matplotlib import pyplot as plt
plt.boxplot([[1,4],[2,5],[3,6]], positions=[2,4,5.5])
By default it uses the values [1, 2, ..., n] but you can specify a different x position for each bar and the xticks will be updated automatically.
Related
graph
how do I make this graph infill all the square around it? (I colored the part that I want to take off in yellow, for reference)
Normally I use two methods to adjust axis limits depending on a situation.
When a graph is simple, axis.set_ylim(bottom, top) method is a quick way to directly change y-axis (you might know this already).
Another way is to use matplotlib.ticker. It gives you more utilities to adjust axis ticks in your graph.
https://matplotlib.org/3.1.1/gallery/ticks_and_spines/tick-formatters.html
I'm guessing you're using a list of strings to set yaxis tick labels. You may want to set locations (float numbers) and labels (string) of y-axis ticks separatedly. Then set the limits on locations like the following snippet.
import matplotlib.pyplot as plt
import matplotlib.ticker as mt
fig, ax = plt.subplots(1,1)
ax.plot([0,1,2], [0,1,2])
ax.yaxis.set_major_locator(mt.FixedLocator([0,1,2]))
ax.yaxis.set_major_formatter(mt.FixedFormatter(["String1", "String2", "String3"]))
ax.set_ylim(bottom=0, top=2)
It gives you this: generated figure
Try setting the min and max of your x and y axes.
I'm trying to create plots which show the correlation of the "value" parameter to different categorical parameters. Here's what I have so far:
plot = sns.pairplot(df, x_vars=['country', 'tier_code', 'industry', 'company_size', 'region'], y_vars=['value'], height=10)
Which produces the following set of plots:
As you can see, the x axis is extremely crowded for the "country" and "industry" plots. I would like to rotate the category labels 90 degrees so that they wouldn't overlap.
All the examples for rotating I could find were for other kinds of plots and didn't work for the pairplot. I could probably get it to work if I made each plot separately using catplot, but I would like to make them all at once. Is that possible?
I am using Google Colab in case it makes any difference. My seaborn version number is 0.10.0.
Manish's answer uses the get_xticklabels method, which doesn't always play well with the higher level seaborn functions in my experience. So here's a solution avoiding that. Since I don't have your data, I'm using seaborn's tips dataset for an example.
I'm naming the object returned by sns.pairplot() grid, just to remind us that it is a PairGrid instance. In general, its axes attribute yields a two-dimensional array of axes objects, corresponding to the subplot grid. So I'm using the flat method to turn this into a one-dimensional array, although it wouldn't be necessary in your special case with only one row of subplots.
In my example I don't want to rotate the labels for the third subplot, as they are single digits, so I slice the axes array accordingly with [:2].
import seaborn as sns
sns.set()
tips = sns.load_dataset("tips")
grid = sns.pairplot(tips, x_vars=['sex', 'day', 'size'], y_vars=['tip'])
for ax in grid.axes.flat[:2]:
ax.tick_params(axis='x', labelrotation=90)
You can rotate x-axis labels as:
plot = sns.pairplot(df, x_vars=['country', 'tier_code', 'industry', 'company_size', 'region'],
y_vars=['value'], height=10)
rotation = 90
for axis in plot.fig.axes: # get all the axis
axis.set_xticklabels(axis.get_xticklabels(), rotation = rotation)
plot.fig.show()
Hope it helps.
I am plotting a bar graph using matplotlib and according to a condition in my code I need to change the color of one of the bar. Is it possible to change the color of a single bar in the plot without plotting a new bar graph, because that would increase the complexity ?
Related: how to change the color of a single bar if condition is True matplotlib
matplotlib.pyplot.bar returns a matplotlib.container.BarContainer, in which the individual bars are stored as matplotlib.patches.Rectangle objects. Given that
The container can be treated as a tuple of the patches themselves. Additionally, you can access these and further parameters by the attributes
You can extract the patch for the specific bar or bars you want and change its color. An example:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 5)
bars = plt.bar(x, x)
bars[2].set_color('orange')
plt.show()
I am trying to plot a data and function with matplotlib 2.0 under python 2.7.
The x values of the function are evolving with time and the x is first decreasing to a certain value, than increasing again.
If the function is plotted against time, it shows function like this plot of data against time
I need the same x axis evolution for plotting against real x values. Unfortunately as the x values are the same for both parts before and after, both values are mixed together. This gives me the wrong data plot:
In this example it means I need the x-axis to start on value 2.4 and decrease to 1.0 than again increase to 2.4. I swear I found before that this is possible, but unfortunately I can't find a trace about that again.
A matplotlib axis is by default linearly increasing. More importantly, there must be an injective mapping of the number line to the axis units. So changing the data range is not really an option (at least when the aim is to keep things simple).
It would hence be good to keep the original numbers and only change the ticks and ticklabels on the axis. E.g. you could use a FuncFormatter to map the original numbers to
np.abs(x-tp)+tp
where tp would be the turning point.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker
x = np.linspace(-10,20,151)
y = np.exp(-(x-5)**2/19.)
plt.plot(x,y)
tp = 5
fmt = lambda x,pos:"{:g}".format(np.abs(x-tp)+tp)
plt.gca().xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(fmt))
plt.show()
One option would be to use two axes, and plot your two timespans separately on each axes.
for instance, if you have the following data:
myX = np.linspace(1,2.4,100)
myY1 = -1*myX
myY2 = -0.5*myX-0.5
plt.plot(myX,myY, c='b')
plt.plot(myX,myY2, c='g')
you can instead create two subplots with a shared y-axis and no space between the two axes, plot each time span independently, and finally, adjust the limits of one of your x-axis to reverse the order of the points
fig, (ax1,ax2) = plt.subplots(1,2, gridspec_kw={'wspace':0}, sharey=True)
ax1.plot(myX,myY1, c='b')
ax2.plot(myX,myY2, c='g')
ax1.set_xlim((2.4,1))
ax2.set_xlim((1,2.4))
I would like to position a single boxplot at a custom position like so:
import pylab as plt
import numpy as np
a=np.random.randn(1000)
plt.boxplot(a, positions=np.array([2.]))
but it always appears at 1. Note that plt.violinplot(a, positions=np.array([2.])) works as expected.
I believe it is plotted at the correct position, it's just that the label on the axis is still set to 1. You can see this if you try to plot something else on the axes. For instance, if you do pyplot.plot([1, 2, 3], [3, 0, -3]) you will see that the middle of line crosses through the middle of the boxplot.
This means things will show up in the right places if you're plotting other stuff on the same axes as the boxplot. If you're not plotting anything else on the same axes, it doesn't really matter where the boxes are actually located; you can just set the labels directly by using the labels argument to boxplot.