Matplotlib 获取seaborn箱线图框的精确数据坐标

Matplotlib 获取seaborn箱线图框的精确数据坐标,matplotlib,seaborn,Matplotlib,Seaborn,我有一个seaborn boxplot(sns.boxplot),我想在上面添加一些要点。例如,假设我有以下数据帧: [In] import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns df = pd.DataFrame({'Property 1':['a']*100+['b']*100,

我有一个seaborn boxplot(
sns.boxplot
),我想在上面添加一些要点。例如,假设我有以下数据帧:

[In]  import pandas as pd
      import numpy as np
      import matplotlib.pyplot as plt
      import seaborn as sns

      df = pd.DataFrame({'Property 1':['a']*100+['b']*100,
                         'Property 2': ['w', 'x', 'y', 'z']*50,
                         'Value': np.random.normal(size=200)})
      df.head(3)

[Out]         Property 1    Property 2  Value
           0    a               w       1.421380
           1    a               x      -1.034465
           2    a               y       0.212911
[In]  df.shape
[Out] (200, 3)
我可以使用seaborn轻松生成箱线图:

[In]  sns.boxplot(x='Property 2', hue='Property 1', y='Value', data=df)
[Out]

现在假设我想为我的样本中的特定案例添加标记。我可以接近这一点:

[In]   specific_case = pd.DataFrame([['a', 'w', '0.5'],
                                     ['a', 'x', '0.2'],
                                     ['a', 'y', '0.1'],
                                     ['a', 'z', '0.3'],
                                     ['b', 'w', '-0.5'],
                                     ['b', 'x', '-0.2'],
                                     ['b', 'y', '0.3'],
                                     ['b', 'z', '0.5']
                                    ], 
                                    columns = df.columns
                                   )
[In]  sns.boxplot(x='Property 2', hue='Property 1', y='Value', data=df)
      plt.plot(np.arange(-0.25, 3.75, 0.5),
               specific_case['Value'].values, 'ro')
[Out] 

当然,这并不令人满意

然后,我使用它讨论如何获取
bBox
,以及如何将diplay坐标转换为数据坐标来编写此函数:

[In] def get_x_coordinates_of_seaborn_boxplot(ax, x_or_y):
         display_coordinates = []
         inv = ax.transData.inverted()    
         for c in ax.get_children():
             if type(c) == mpl.patches.PathPatch:
                 if x_or_y == 'x':         
                     display_coordinates.append(
                         (c.get_extents().xmin+c.get_extents().xmax)/2)
                 if x_or_y == 'y':
                     display_coordinates.append(
                         (c.get_extents().ymin+c.get_extents().ymax)/2)
         return inv.transform(tuple(display_coordinates)) 
这对我的第一种色调非常有效,但对第二种色调则完全无效:

[In]  ax = sns.boxplot(x='Property 2', hue='Property 1', y='Value', data=df)
      coords = get_x_coordinates_of_seaborn_boxplot(ax, 'x')
      plt.plot(coords, specific_case['Value'].values, 'ro')
[Out] 


我怎样才能得到我所有盒子的数据坐标?

我不确定这些转换的目的。但真正的问题似乎只是将
特定案例中的点绘制在正确的位置。每个箱线图的X坐标从整数偏移0.2。(这是因为默认情况下,条形图的宽度为0.8,因此有两个框,每个框的宽度为0.4,其中一半为0.2。)
然后,您需要排列x值,以适合
特定情况下的数据帧

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

df = pd.DataFrame({'Property 1':['a']*100+['b']*100,
                 'Property 2': ['w', 'x', 'y', 'z']*50,
                 'Value': np.random.normal(size=200)})

specific_case = pd.DataFrame([['a', 'w', '0.5'],
                             ['a', 'x', '0.2'],
                             ['a', 'y', '0.1'],
                             ['a', 'z', '0.3'],
                             ['b', 'w', '-0.5'],
                             ['b', 'x', '-0.2'],
                             ['b', 'y', '0.3'],
                             ['b', 'z', '0.5']
                            ],  columns = df.columns )
ax = sns.boxplot(x='Property 2', hue='Property 1', y='Value', data=df)

X = np.repeat(np.atleast_2d(np.arange(4)),2, axis=0)+ np.array([[-.2],[.2]]) 
ax.plot(X.flatten(), specific_case['Value'].values, 'ro', zorder=4)

plt.show()