add legend seaborn barplot - python

Here is my code :
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
array = np.array([[1,5,9],[3,5,7]])
df = pd.DataFrame(data=array, index=['Positive', 'Negative'])
f, ax = plt.subplots(figsize=(8, 6))
current_palette = sns.color_palette('colorblind')
ax_pos = sns.barplot(x = np.arange(0,3,1), y = df.loc['Positive'].to_numpy(), color = current_palette[2], alpha = 0.66)
ax_neg = sns.barplot(x = np.arange(0,3,1), y = df.loc['Negative'].to_numpy(), color = current_palette[4], alpha = 0.66)
plt.xticks(np.arange(0,3,1), fontsize = 20)
plt.yticks(np.arange(0,10,1), fontsize = 20)
plt.legend((ax_pos[0], ax_neg[0]), ('Positive', 'Negative'))
plt.tight_layout()
Unfortunately, I have this error :
TypeError: 'AxesSubplot' object does not support indexing
I would like to know why calling legend like this (plt.legend(ax[0]...) is not possible with seaborn whereas with matplotlib it is.
In the end, I just want the legend in the upper left corner.

I figured out that barplot has "label" function :
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
array = np.array([[1,5,9],[3,5,7]])
df = pd.DataFrame(data=array, index=['Positive', 'Negative'])
f, ax = plt.subplots(figsize=(8, 6))
current_palette = sns.color_palette('colorblind')
sns.barplot(x = np.arange(0,3,1), y = df.loc['Positive'].to_numpy(), color = current_palette[2], alpha = 0.66, label = "Positive")
sns.barplot(x = np.arange(0,3,1), y = df.loc['Negative'].to_numpy(), color = current_palette[4], alpha = 0.66, label = "Negative")
plt.xticks(np.arange(0,3,1), fontsize = 20)
plt.yticks(np.arange(0,10,1), fontsize = 20)
plt.legend(frameon = False)
plt.tight_layout()

Related

Here is a snippet of a plot. I am not able to manually set the y-axis range started from 1400 to max. Conventional method is not working in bar plot

How can i change my y-axis range manually
import numpy as np
import matplotlib.pyplot as plt
a1 = np.linspace(0.5,3.0,20)
d2 = np.array([1357.20029811, 1518.79648166, 1636.42791465, 1720.7907639 ,
1779.8196137 , 1819.45852936, 1844.19713989, 1857.45123917,
1861.83690162, 1859.37001519, 1851.61278982, 1839.7821616 ,
1824.83057928, 1807.50662414, 1788.40080137, 1767.98035494,
1746.61590397, 1724.6019459 , 1702.17273138, 1679.51462449])
d1 = np.array([0.55,1.16,1.736,2.28])
data2 = np.array([1424.6123596 , 1819.96128591, 1856.87393688, 1797.60859988])
D = np.array([3.342,8.22,15.19,23.70])
fig = plt.figure(figsize = (7, 5))
plt.plot(a1,d2,'--',color='y')
plt.errorbar(d1,data2, yerr = D,color='g',fmt='o', markersize=5, capsize=5)
plt.legend(fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
from matplotlib.ticker import StrMethodFormatter
plt.bar(d1, data2, color ='maroon', width = [0.11,0.21,0.33,0.49],alpha = 0.3)
plt.show()
Try the following. As a side note it is a bad practice to "cut" a bar plot. Your users can get a misleading interpretation of the data.
import numpy as np
import matplotlib.pyplot as plt
a1 = np.linspace(0.5,3.0,20)
d2 = np.array([1357.20029811, 1518.79648166, 1636.42791465, 1720.7907639 ,
1779.8196137 , 1819.45852936, 1844.19713989, 1857.45123917,
1861.83690162, 1859.37001519, 1851.61278982, 1839.7821616 ,
1824.83057928, 1807.50662414, 1788.40080137, 1767.98035494,
1746.61590397, 1724.6019459 , 1702.17273138, 1679.51462449])
d1 = np.array([0.55,1.16,1.736,2.28])
data2 = np.array([1424.6123596 , 1819.96128591, 1856.87393688, 1797.60859988])
D = np.array([3.342,8.22,15.19,23.70])
fig = plt.figure(figsize = (7, 5))
plt.plot(a1,d2,'--',color='y')
plt.errorbar(d1,data2, yerr = D,color='g',fmt='o', markersize=5, capsize=5)
plt.legend(fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.ylim([1400, max(d2)])
from matplotlib.ticker import StrMethodFormatter
plt.bar(d1, data2, color ='maroon', width = [0.11,0.21,0.33,0.49],alpha = 0.3)
plt.show()

How to filter data while drawing?

I have a dataframe which I drawed as you can see the figure and codes below;
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
df = pd.read_excel('nötronn.xlsx')
fig, ax = plt.subplots(figsize=(20,40))
ax1 = plt.subplot2grid((1,5), (0,0), rowspan=1, colspan = 1)
ax1.plot(df["N/F*10"], df['Depth'], color = "green", linewidth = 0.5)
ax1.set_xlabel("Porosity")
ax1.xaxis.label.set_color("green")
ax1.set_xlim(10, 50)
ax1.set_ylabel("Depth (m)")
ax1.tick_params(axis='x', colors="green")
ax1.spines["top"].set_edgecolor("green")
ax1.title.set_color('green')
ax1.set_xticks([10, 20, 30, 40, 50])
I want to filter data so that I can realize the differences better. I tried these:
z = np.polyfit(df["N/F*10"], df['Depth'], 2)
p = np.poly1d(z)
plt.plot(df["N/F*10"], p(df["N/F*10"]))
But it gives :LinAlgError: SVD did not converge in Linear Least Squares
How can I solve it? Thanks.
Output expectation:
This works!
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from statsmodels.nonparametric.smoothers_lowess import lowess
data = pd.read_excel('nötronn.xlsx')
sub_data = data[data['Depth'] > 21.5]
result = lowess(sub_data['Eksi'], sub_data['Depth'].values)
x_smooth = result[:,0]
y_smooth = result[:,1]
tot_result = lowess(data['Eksi'], data['Depth'].values, frac=0.01)
x_tot_smooth = tot_result[:,0]
y_tot_smooth = tot_result[:,1]
fig, ax = plt.subplots(figsize=(20, 8))
##ax.plot(data.depth.values, data['N/F*10'], label="raw")
ax.plot(x_tot_smooth, y_tot_smooth, label="lowess 1%", linewidth=3, color="g")
ax.plot(data['GR-V121B-ETi'])
ax.plot(data['Caliper'], linestyle = 'dashed')

Interactive Stock Chart, step by step animation with a slider. Matplolib & Jupyter

In this post: Interactive Stock Chart, step by step animation with keyboard arrows, with Matplolib, I wrote a code, in which the user Zephyr brilliantly fixed, that interactively simulate a stock using keyboard arrows.
It turned out that I found a way of doing the same thing in Jupyter, using the module ipywidgets. The code works, but unfortunately the same chart is plotted twice. I have no idea why this is happening. Can someone help? I just want to show one plot (notice that the second plot does not move as I use the slider).
Here is the code:
%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.read_csv('all_stocks_5yr.csv')
df_apple = df[df['Name'] == 'AAPL'].copy()
df_apple['date'] = pd.to_datetime(df_apple['date'])
df_apple.reset_index(inplace = True)
bars_to_display = 60
step = widgets.IntSlider(value=0, min=0, max=len(df_apple)-bars_to_display)
val_array = []
for idx, val in df_apple.iterrows():
val_array.append(val)
x = np.arange(0, len(df_apple))
fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)
def f(step):
ax.cla()
ax2.cla()
for i in range(step, bars_to_display + step):
color = '#2CA453'
if val_array[i]['open'] > val_array[i]['close']: color = '#F04730'
ax.plot([x[i], x[i]], [val_array[i]['low'], val_array[i]['high']], color = color)
ax.plot([x[i], x[i] - 0.1], [val_array[i]['open'], val_array[i]['open']], color = color)
ax.plot([x[i], x[i] + 0.1], [val_array[i]['close'], val_array[i]['close']], color = color)
ax2.bar(x[i], val_array[i]['volume'], color = 'lightgrey')
display(fig)
display(step)
out = widgets.interactive_output(f, {'step': step})
display(out)
The line:
fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)
draws the first figure. Just add plt.close() after that.
Complete Code
from IPython.display import display
from ipywidgets import interactive, widgets
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
df = pd.read_csv('all_stocks_5yr.csv')
df_apple = df[df['Name'] == 'AAPL'].copy()
df_apple['date'] = pd.to_datetime(df_apple['date'])
df_apple.reset_index(inplace = True)
bars_to_display = 60
step = widgets.IntSlider(value = 0, min = 0, max = len(df_apple) - bars_to_display)
val_array = []
for idx, val in df_apple.iterrows():
val_array.append(val)
x = np.arange(0, len(df_apple))
fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)
plt.close()
def f(step):
ax.cla()
ax2.cla()
for i in range(step, bars_to_display + step):
color = '#2CA453'
if val_array[i]['open'] > val_array[i]['close']: color = '#F04730'
ax.plot([x[i], x[i]], [val_array[i]['low'], val_array[i]['high']], color = color)
ax.plot([x[i], x[i] - 0.1], [val_array[i]['open'], val_array[i]['open']], color = color)
ax.plot([x[i], x[i] + 0.1], [val_array[i]['close'], val_array[i]['close']], color = color)
ax2.bar(x[i], val_array[i]['volume'], color = 'lightgrey')
display(fig)
display(step)
out = widgets.interactive_output(f, {'step': step})
display(out)

matplotlib legend label under key?

How to adjust label location relate to key?I reclassified the data and displayed a discrete corbar which looks like multi-handles legend. Actually ,I couldn't find any parameters about the location of labels(text or numbers).The default setting is keys in left while label in right. Could I change the position? such as labels under keys or above. My purpose is to show the legend as follows (label under key and no space between keys:
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randint(8, size=(100,100))
cmap = plt.cm.get_cmap('PiYG', 8)
plt.pcolormesh(data,cmap = cmap,alpha = 0.75)
# Set borders in the interval [0, 1]
bound = np.linspace(0, 1, 9)
# Preparing borders for the legend
bound_prep = np.round(bound * 7, 2)
# Creating 8 Patch instances
plt.legend([mpatches.Patch(color=cmap(b)) for b in bound[:-1]],
['{}'.format(bound_prep[i]) for i in range(8)],
bbox_to_anchor=(0,-0.25,1,0.2),ncol=len(bound))
It seems that there is no parameters to adjust location of labels.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randint(8, size=(100,100))
cmap = plt.cm.get_cmap('PiYG', 8)
fig, ax = plt.subplots()
pcm = ax.pcolormesh(data,cmap = cmap,alpha = 0.75, vmin=0, vmax=8)
fig.colorbar(pcm, ax=ax)
plt.show()

Remove lowest color from colorbar in Seaborn/Matplotlib

If I set shade_lowest = False, the colorbar still contains the lowest level (purple-ish). Is there any generic way to remove it entirely?
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
a = np.random.normal(0, 1, 100)
b = np.random.normal(0, 1, 100)
fig, ax = plt.subplots()
sns.kdeplot(a, b, shade = True, shade_lowest = False, cmap = "viridis", cbar = True, n_levels = 4, ax = ax)
plt.show()
A solution is for sure to not create this level from the beginning.
Here we choose maximally 5 levels according to a locator and remove the lowest one when calling the contourf plot, such that this level does not even exist in the first place. Then the automatic colorbar creation works flawlessly.
import numpy as np; np.random.seed(5)
import matplotlib.pyplot as plt
from matplotlib import ticker
from scipy import stats
x = np.random.normal(3, 1, 100)
y = np.random.normal(0, 2, 100)
X, Y = np.mgrid[x.min():x.max():100j, y.min():y.max():100j]
positions = np.vstack([X.ravel(),Y.ravel()])
values = np.vstack([x,y])
kernel = stats.gaussian_kde(values)
Z = np.reshape(kernel(positions).T, X.shape)
N=4
locator = ticker.MaxNLocator(N + 1, min_n_ticks=N)
lev = locator.tick_values(Z.min(), Z.max())
fig, ax = plt.subplots()
c = ax.contourf(X,Y,Z,levels=lev[1:])
ax.scatter(x,y, s=9, c="k")
fig.colorbar(c)
plt.show()

Categories

Resources