使用Pandas在Boxplot中标记特定值

时间:2017-12-14 13:02:21

标签: python pandas seaborn boxplot

我使用pandas dataframe创建了一个boxplot,现在我想在同一个图中标记特定的值,使用" X" (希望在尖叫的红色!)。

一些数据:

df = pd.DataFrame(
[
[2, 4, 5, 6, 1],
[4, 5, 6, 7, 2],
[5, 4, 5, 5, 1],
[10, 4, 7, 8, 2],
[9, 3, 4, 6, 2],
[3, 3, 4, 4, 1]
], columns=['a1', 'a2', 'a3', 'a4', 'b'])

mark_values = pd.DataFrame(
[
[2,1],
[8.25,2]
], columns=['a1', 'b'])

df_long = pd.melt(df, "b", var_name="a", value_name="c")
g = sns.boxplot(x='c', y='a', hue='b', data=df_long, 
palette=sns.color_palette("Blues_d"), orient='h')
sns.despine(left=True)

这会生成一个箱线图。我现在想要将标记添加为红色十字形,例如标记类别 a1 ,子组 1 ,其中X位于" 4"和子组 2 ,其中X位于&# 34; 8.25"等等,仍然保留我的漂亮的箱形图。

应标记要标记的值,并将其存储为上面定义的数据框mark_values。如示例所示:

mark_values

Out[1]: 
     a1  b
0  4.00  1
1  8.25  2

对此有任何简单的解决方案吗?

由于

2 个答案:

答案 0 :(得分:0)

由于Seaborn是使用matplotlib构建的,因此您可以使用text

import pandas as pd
import seaborn as sns

df = pd.DataFrame(
[
[2, 4, 5, 6, 1],
[4, 5, 6, 7, 2],
[5, 4, 5, 5, 1],
[10, 4, 7, 8, 2],
[9, 3, 4, 6, 2],
[3, 3, 4, 4, 1]
], columns=['a1', 'a2', 'a3', 'a4', 'b'])

mark_values = pd.DataFrame(
[
[2,1],
[8.25,2]
], columns=['a1', 'b'])

df_long = pd.melt(df, "b", var_name="a", value_name="c")
g = sns.boxplot(x='c', y='a', hue='b', data=df_long, 
palette=sns.color_palette("Blues_d"), orient='h')
sns.despine(left=True)
g.text(4,0.1,'X', fontsize=50, color='red')
g.text(8.25,.5,'X', fontsize=50, color='red')

enter image description here

X轴只是c的值。但您也可以使用get_ylim()来获得所需的输出。您还可以使用np.linspace来获得均匀间隔的值:

import numpy as np
print(g.get_ylim())
print(str(g.get_ylim()[0]) + ' is the low value')
print(str(g.get_ylim()[1]) + ' is the high value')
print(np.linspace(g.get_ylim()[0], g.get_ylim()[1], 4))

请注意,'X'的左下角将位于X轴和Y轴的确切位置。因此,字体大小为50使得它看起来像X“关闭”时太大了。您可能需要使用这些值,以便'X'位于正确的位置。但是根据你的问题,我不确定你想要X有多大。

看看这里的差异。 -.08.1似乎是30的字体大小的良好调整。绿色“X”使用这些调整后的值。

g.text(4,2.1666,'X', fontsize=30, color='red')
g.text(4 - (4*.08) ,2.1666 + (2.1666 * .1),'X', fontsize=30, color='green')

enter image description here

答案 1 :(得分:0)

首先我想有必要定义mark_values以包含一个列,该列指定应标记哪个"a",例如标记"a1",将1放在一列中。

      c  a  b
0  2.00  1  1
1  8.25  1  2

然后,您可以使用“x”作为标记绘制散点图,其中散点坐标为水平方向的列c,垂直方向由

给出
y = (a-1)+(b-1.5)*0.4

解释一下:

  • a从1开始,但第一个类别绘制为0,
  • 此处所有b值之间的平均值为1.5。
  • 条宽的一半是0.4

总的来说,这给出了:

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns


df = pd.DataFrame( [[2, 4, 5, 6, 1],
                    [4, 5, 6, 7, 2],
                    [5, 4, 5, 5, 1],
                    [10, 4, 7, 8, 2],
                    [9, 3, 4, 6, 2],
                    [3, 3, 4, 4, 1]], 
                columns=['a1', 'a2', 'a3', 'a4', 'b'])

mark_values = pd.DataFrame( [ [2,1,1], [8.25,1,2], [4,3,2] ], columns=['c',"a",'b'])
print mark_values
df_long = pd.melt(df, "b", var_name="a", value_name="c")

ax = sns.boxplot(x='c', y='a', hue='b', data=df_long, 
                palette=sns.color_palette("Blues_d"), orient='h')
sns.despine(left=True)

y = (mark_values["a"].values - 1)+(mark_values["b"].values-1.5)*0.4
ax.scatter(mark_values["c"].values, y, marker="x", c="red", s=400, lw=6)

plt.show()

enter image description here