I would like to draw box-plot for below data set but I don't need tails . I need a rectangle with max and min on edges . By the way it does not have to be a rectangle it could be a thick line
Please help.
Thank you.
import seaborn as sns
import pandas as pd
df=pd.DataFrame({'grup':['a','a','a','a','b','b','b','c','c','c','c','c','c','c'],'X1':
[10,9,12,5,20,43,28,40,65,78,65,98,100,150]})
df
ax = sns.boxplot(x="grup", y="X1", data=df, palette="Set3")
CodePudding user response:
You can create a barplot, using the minimums as 'bottom' and the difference between maximums and minimums as heights.
Note that a barplot has a "sticky" bottom, fixing the lowest point of the y-axis to the lowest bar. As a remedy, we can change the ylim.
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'grup': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c'],
'X1': [10, 9, 12, 5, 20, 43, 28, 40, 65, 78, 65, 98, 100, 150]})
grups = np.unique(df['grup'])
bottoms = [df[df['grup'] == g]['X1'].min() for g in grups]
heights = [df[df['grup'] == g]['X1'].max() - g_bottom for g, g_bottom in zip(grups, bottoms)]
ax = sns.barplot(x=grups, y=heights, bottom=bottoms, palette="Set3", ec='black')
# for reference, show where the values are; leave this line out for the final plot
sns.stripplot(x='grup', y='X1', color='red', s=10, data=df, ax=ax)
ax.set_xlabel('grup') # needed because the barplot isn't directly using a dataframe
ax.set_ylabel('X1')
ax.set_ylim(ymin=0)
Update: adding the minimum and maximum values:
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'grup': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c'],
'X1': [10, 9, 12, 5, 20, 43, 28, 40, 65, 78, 65, 98, 100, 150]})
grups = np.unique(df['grup'])
bottoms = np.array([df[df['grup'] == g]['X1'].min() for g in grups])
tops = np.array([df[df['grup'] == g]['X1'].max() for g in grups])
ax = sns.barplot(x=grups, y=tops - bottoms, bottom=bottoms, palette="Set3", ec='black')
ax.set_xlabel('grup') # needed because the barplot isn't directly using a dataframe
ax.set_ylabel('X1')
ax.set_ylim(ymin=0)
for i, (grup, bottom, top) in enumerate(zip(grups, bottoms, tops)):
ax.text(i, bottom, f'\n{bottom}', ha='center', va='center')
ax.text(i, top, f'{top}\n', ha='center', va='center')