I have a set of subplots to plot. Here, how do we set the interval for x-axis in the subplot in second row, i.e ax4 to ax6. Currently all the values from 1 to 100 are printed as shown in the figure. I tried ax4.set_xticks(range(1,100,5)). But there, the range shown was 1 to 20. I was expecting a range from 1 to 100, with an interval of 5, i.e. 1,5,10...95,100
Currently the plot has x-axis as shown below. I have not added the code for first row.
yInit = initRes
yInit = yInit[(yInit['nodeSKT'] < 92) & (yInit['nodeSKT'] > 1)]
sns.set_context("paper", font_scale=2, rc={"lines.linewidth": 1.2})
fig, (ax4, ax5, ax6) = plt.subplots(nrows=1,ncols=3,figsize=(18,10))
plt.figure()
xval = 'nodeSKT'
sns.pointplot(x=xval, y='lemmaPrec', data=yInit,join=False,ax=ax4)
sns.pointplot(x=xval, y='wordPrec',color="#2ecc71",data=yInit, join=False,ax=ax4)
sns.pointplot(x=xval, y='lemmaReca', data=yInit,join=False,ax=ax5)
sns.pointplot(x=xval, y='wordReca',color="#2ecc71",data=yInit, join=False,ax=ax5)
sns.pointplot(x=xval, y='lemmaFsco', data=yInit,join=True,ax=ax6)
sns.pointplot(x=xval, y='wordFsco',color="#2ecc71",data=yInit, join=False,ax=ax6)
plt.savefig('lem_fscore.png')
Seaborn pointplot is a categorical plot. This means that the different categories are simply placed one by one along the x axis.
The idea would therefore be to change the locator as well as the formatter for the xticks.
import seaborn.apionly as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np; np.random.seed(1)
x = np.random.randint(0,20,size=(100))
y = np.random.rand(100)
ax = sns.pointplot(x,y )
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
plt.show()
Related
I'm trying to make it so the ticks on the x-axis for revenue show the value as a factor of a million rather than as a factor of a hundred million as they are now. I can't seem to figure out how to accomplish this. My code and the resulting bar chart is below.
import numpy as np
import pandas as pd
import matplotlib.ticker as plticker
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import display
from pandas import Series
%matplotlib inline
# Define Figure Size
fig, ax = plt.subplots(figsize=(25,25))
# Get the average vote_average for each genre
average_revenue = df2.groupby('release_year')['revenue_adj'].mean()
# Find positions of y ticks
y_pos = np.arange(len(df2['release_year'].unique()))
# Set up Bar Chart
ax.set_yticks(y_pos)
ax.set_yticklabels(sorted(df2['release_year'].unique()))
ax.set_xlabel('Revenue in Millions', fontsize=16)
ax.set_ylabel('Release Year', fontsize=16)
ax.set_title('Revenue by Release Year', fontsize=20)
# Set Size of X and Y labels
plt.rc('xtick', labelsize=14)
plt.rc('ytick', labelsize=14)
# Put Values next to Each Bar
for i, v in enumerate(average_revenue):
a = v/1000000
ax.text(v, i, ('$' + str(round(a,2)) + 'M'), color='blue')
ax.invert_yaxis() # labels read top-to-bottom
# Draw Bar Chart
ax.barh(y_pos, average_revenue, align='center', color='green', ecolor='black')
Right now, the data is shown in ones, not millions or hundreds of millions. Notice the 1e8 on the right of the plot. You can plot the value in millions by dividing the input by a million:
ax.barh(y_pos, average_revenue * 1e-6, ...)
Alternatively, you can adjust the formatter on the x-axis if you prefer not to alter the data. For example, you could use a FuncFormatter like this:
from matplotlib.ticker import FuncFormatter
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: f'{x * 1e-6:0.1f}'))
As you can see here, the X axis labels here are quite unreadable. This will happen regardless of how I adjust the figure size. I'm trying to figure out how to adjust the labeling so that it only shows certain points. The X axis are all numerical between -1 to 1, and I think it would be nice and more viewer friendly to have labels at -1, -.5, 0, .5 and 1.
Is there a way to do this? Thank you!
Here's my code
sns.set(rc={'figure.figsize':(20,8)})
ax = sns.countplot(musi['Positivity'])
ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha='right')
plt.tight_layout()
plt.show()
Basically seaborn is wrapper on matplotlib. You can use matplotlib ticker function to do a Job. Refer the below example.
Let's Plots tick every 1 spacing.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
sns.set_theme(style="whitegrid")
x = [0,5,9,10,15]
y = [0,1,2,3,4]
tick_spacing = 1
fig, ax = plt.subplots(1,1)
sns.lineplot(x, y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()
Now Let's plot ticks every 5 ticks.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
sns.set_theme(style="whitegrid")
x = [0,5,9,10,15]
y = [0,1,2,3,4]
tick_spacing = 5
fig, ax = plt.subplots(1,1)
sns.lineplot(x, y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()
P.S.: This solution give you explicit control of the tick spacing via the number given to ticker.MultipleLocater(), allows automatic limit determination, and is easy to read later.
I need to plot a time series. Dates on the X axis and values on the Y axsis, but I also need to specify the day of week on the X axsis.
ax = sns.lineplot(x='date', y='value', data=df)
I expect to be able to add day of week (another column from df) on the X axis.
example with Excel
You can try to do this by adding a second x-axis. Please find below a code you'll need to adapt to your problem. I guess there are better ways to do that but it should works.
from matplotlib.ticker import MultipleLocator
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
x = np.arange(1000)
x2 = np.arange(1000)*2
y = np.sin(x/100.)
fig = plt.figure()
ax = plt.subplot(111)
sns.lineplot(x, y)
plt.xlim(0, 1000)
ax.xaxis.set_major_locator(MultipleLocator(200))
ax2 = ax.twiny()
sns.lineplot(x2, y, visible=False)
plt.xlim(0, 2000)
ax2.xaxis.set_major_locator(MultipleLocator(400))
ax2.spines['top'].set_position(('axes', -0.15))
ax2.spines['top'].set_visible(False)
plt.tick_params(which='both', top=False)
In the code below Matplotlib gives the correct range of 5.0 to 10.0, why is Seaborn different?
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from matplotlib import ticker
sns.set()
fig, (ax1, ax2) = plt.subplots(2)
x = np.linspace(5, 10)
y = x ** 2
sns.barplot(x, y, ax=ax1)
ax1.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax1.xaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))
ax2.bar(x, y, width = 0.1)
ax2.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax2.xaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))
plt.show()
Seaborn's barplot is a categorical plot. This means it places the bars at successive integer positions (0,1,...N-1). Hence, if you have N bars, the axis will range from -0.5 to N-0.5.
There is no way to tell seaborn to place the bars at different positions; but you can of course fake the labels to let it appear as such. E.g. to label every 5th bar with the value from x:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from matplotlib import ticker
sns.set()
fig, ax = plt.subplots()
x = np.linspace(5, 10)
y = x ** 2
sns.barplot(x, y, ax=ax)
ax.xaxis.set_major_locator(ticker.FixedLocator(np.arange(0, len(x), 5)))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(x[::5]))
ax.tick_params(axis="x", rotation=90)
plt.tight_layout()
plt.show()
Inversely, it is possible to plot categorical plots with matplotlib. To this end, one needs to plot strings.
ax.bar(x.astype(str), y)
ax.xaxis.set_major_locator(ticker.FixedLocator(np.arange(0, len(x), 5)))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(x[::5]))
ax.tick_params(axis="x", rotation=90)
If you want a numerical bar plot, i.e. a plot where each bar is at the axis position of x, you would need to use matplotlib. This is the default case also shown in the question, where the bars range between 5 and 10. One should make sure to have the width of the bars smaller than the difference between successive x positions in this case.
ax.bar(x, y, width=np.diff(x).mean()*0.8)
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))
ax.tick_params(axis="x", rotation=90)
I've created a cumulative probability plot with StatsModels in Python, but there are way too many ticks on the axis.
I want there to be only be tick marks at 0.1, 10, 50, 90, 99, and 99.9. Anyone know how to make this work? I tried using the code below but it only gives me the first n number of ticks, making it pretty useless (See figure below.)
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker
import statsmodels.api as sm
csv = pd.read_csv('cumProbMaxData.csv')
data = csv.values.tolist()
flat_list = [item for sublist in data for item in sublist]
fig,ax = plt.subplots()
x = np.array(flat_list)
pp_x = sm.ProbPlot(x, fit=True)
figure = pp_x.probplot(exceed=False, ax=ax, marker='.', color='k', markersize=12)
plt.xlabel('Cumulative Probability (%)')
plt.ylabel('Maximum CO$_2$ Flux (g m$^-$$^2$ d$^-$$^1$)')
tick_spacing=5
ax.xaxis.set_major_locator(ticker.MaxNLocator(tick_spacing))
plt.tight_layout()
plt.show()
Statsmodels ProbPlot plots the data in their real units. It is only the axes ticks which are then changed as to show some percentage value. This is in general bad style but of course you have to live with it if you want to use ProbPlot.
A solution for the problem of showing less ticks on such a plot which uses a FixedLocator and FixedFormatter would be to subsample the shown ticks. The ticklabels you want to show are at indices locs = [0,3,6,10,14,17,20] (you want to show the ticklabel 0, 3, 6, etc.).
You can use this list to select from the shown ticks only those in the list as shown below.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import statsmodels.api as sm
x = np.random.randn(200)
fig,ax = plt.subplots()
pp_x = sm.ProbPlot(x, fit=True)
pp_x.probplot(exceed=False, ax=ax, marker='.', color='k', markersize=12)
locs = [0,3,6,10,14,17,20]
ax.set_xticklabels(np.array(ax.xaxis.get_major_formatter().seq)[locs])
ax.set_xticks(ax.get_xticks()[locs])
plt.tight_layout()
plt.show()