python - 如何确定平均线 fiddle 图边缘的 x 值

标签 python matplotlib seaborn violin-plot

我试图在 fiddle 图上画一条平均线,因为我无法找到一种方法让 sns 替换来自“四分位数”的“中值”线,我决定编码,以便对于每种情况绘制在顶部。我计划使用 plt.plot 在我拥有的三个图表的平均值(y 值)上绘制水平线。

我有精确的 y(高度)值,我希望在其中绘制水平线,但是,我很难尝试找出每个 fiddle 图在该特定 y 值上的边界。我知道因为它是对称的,所以域是 (-x, x),所以我需要一种方法来找到“x”值,以便能够添加 3 条水平线,每条水平线都以我拥有的 fiddle 图为界。

这是我的代码,plt.plot的x值为-0.37,这是我通过反复试验发现的,我想要python为我找到给定 y 值的值。

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

data = [2.57e-05, 4.17e-06, -5.4e-06, -5.05e-06, 1.15e-05, -6.7e-06, 1.01e-05, 5.53e-06, 8.13e-06, 1.27e-05, 1.11e-06, -2.87e-06, -1.38e-06, -1.07e-05, -8.04e-06, 4.77e-06, 3.22e-07, 9.86e-06, 1.38e-05, 1.32e-05, -3.48e-06, -4.69e-06, 8.15e-06, 4.21e-07, 2.71e-06, 7.52e-08, 1.04e-06, -1.92e-06, -4.08e-06, 4.76e-06]

vg = sns.violinplot(data=data, inner="quartile", scale="width")
    
a = sns.pointplot(data=data, zlinestyles='-', join=False, ci=None, color='red')
        
for p in vg.lines:
    p.set_linestyle('-')
    p.set_linewidth(0.8)  # Sets the thickness of the quartile lines 
    p.set_color('white')  # Sets the color of the quartile lines 
    p.set_alpha(0.8)

for p in vg.lines[1::3]:  # these are the median lines; not means
    p.set_linestyle('-')
    p.set_linewidth(0)  # Sets the thickness of the median lines 
    p.set_color('black')  # Sets the color of the median lines 
    p.set_alpha(0.8)

# add a mean line from the edge of the violin plot
plt.plot([-0.37, 0], [np.mean(data), np.mean(data)], 'k-', lw=1)
plt.show()

enter image description here

请参阅我删除了中点但留下四分位线的图片,我想在其中画出蓝色点可见的平均线

这是我用通过试验和错误找到的 x 值绘制 plt.plot 后的图片:仅适用于情况 I

The image

最佳答案

您可以画一条太长的线,然后用形成 fiddle 的多边形将其剪裁。

请注意,inner='quartile' 显示 25%、50% 和 75% 线。 50% 线也称为中位数。这类似于 boxplots通常是绘制的。以过于相似的方式显示均值是相当令人困惑的。这就是为什么seaborn(和许多其他库)更喜欢将平均值显示为一个点。

这里是一些示例代码(请注意,sns.violinplot 的返回值是一个 ax,并且其命名非常不同,因此很难找到进入的方法matplotlib 和 seaborn 文档和示例)。

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

tips = sns.load_dataset('tips')
tips['day'] = pd.Categorical(tips['day'])

ax = sns.violinplot(data=tips, x='day', y='total_bill', hue='day', inner='quartile', scale='width', dodge=False)
sns.pointplot(data=tips, x='day', y='total_bill', join=False, ci=None, color='yellow', ax=ax)
ax.legend_.remove()

for p in ax.lines:
    p.set_linestyle('-')
    p.set_linewidth(0.8)  # Sets the thickness of the quartile lines
    p.set_color('white')  # Sets the color of the quartile lines
    p.set_alpha(0.8)
for x, (day, violin) in enumerate(zip(tips['day'].cat.categories, ax.collections)):
    line = ax.hlines(tips[tips['day'] == day]['total_bill'].mean(), x - 0.5, x + 0.5, color='black', ls=':', lw=2)
    patch = PathPatch(violin.get_paths()[0], transform=ax.transData)
    line.set_clip_path(patch)  # clip the line by the form of the violin
plt.show()

violinplot with line for the mean

更新为使用数据列表列表:

data = [np.random.randn(10, 7).cumsum(axis=0).ravel() for _ in range(3)]

ax = sns.violinplot(data=data, inner='quartile', scale='width', palette='Set2')
# sns.pointplot(data=data, join=False, ci=None, color='red', ax=ax) # shows the means
ax.set_xticks(range(len(data)))
ax.set_xticklabels(['I' * (k + 1) for k in range(len(data))])

for p in ax.lines:
    p.set_linestyle('-')
    p.set_linewidth(0.8)  # Sets the thickness of the quartile lines
    p.set_color('white')  # Sets the color of the quartile lines
    p.set_alpha(0.8)
for x, (data_x, violin) in enumerate(zip(data, ax.collections)):
    line = ax.hlines(np.mean(data_x), x - 0.5, x + 0.5, color='black', ls=':', lw=2)
    patch = PathPatch(violin.get_paths()[0], transform=ax.transData)
    line.set_clip_path(patch)
plt.show()

violinplot from lists, with mean line

PS:关于enumerate(zip(...))的一些进一步解释

  • for data_x in data: 将循环遍历列表 data 的条目,首先将 data[0] 分配给 data_x 等等
  • for x, data_x in enumerate(data): 将循环遍历列表 data 的条目,同时递增变量 x01,最后到 2
  • for data_x, violin in zip(data, ax.collections):data_x 循环遍历列表 data 的条目,并且同时变量violin通过存储在ax.collections中的列表(这是matplotlib存储 fiddle 形状的地方)
  • for x, (data_x, violin) in enumerate(zip(data, ax.collections)):将枚举与 zip` 结合起来

关于python - 如何确定平均线 fiddle 图边缘的 x 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69246332/

相关文章:

python - 如何在 Python 中合并 Apache-Beam DataFlow 中的解析文本文件?

python - 我可以告诉 python 将现有图形放入新图形中吗?

python - 如何减少 seaborn 中 x 轴原点和 y 轴原点之间的空间

python - Python 函数中的意外缩进

python - 如何在pandas python中逐步连续计算相同行之间的时间差

python - 在`decimal.Decimal(1.0/3.0)`中有27位额外的精度吗?

python - 从 Matplotlib 集合中检索标记

python - numpy记录数组中列的数据类型转换

python - Seaborn 热图子图 - 保持轴比一致

python - 按条件标准化条件单变量seaborn