You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加散点图后小提琴图被挤压至一侧,求正确叠加绘制方法

问题描述

希望创建带有自定义标记的双小提琴图,目前已成功绘制出小提琴图,但添加各类标记的散点图后,小提琴图的布局被破坏(小提琴图的阴影被挤到左侧),需要实现两者的正确叠加绘制。

原代码:

def plot_psd(centralised_frequencies,centralised_psds,distributed_frequencies,distributed_psds):
    fig,ax=plt.subplots(1,1,figsize=(10,5))
    
    add_label(ax.violinplot(centralised_psds,side='high',showmeans=False,showmedians=False,showextrema=False), "Centralised Control")
    ax.set_xticklabels(centralised_frequencies)
    add_label(ax.violinplot(distributed_psds,side='low',showmeans=False,showmedians=False,showextrema=False), "Distributed Control")
    ax.set_xticklabels(distributed_frequencies)
    ax.scatter(centralised_frequencies,np.mean(centralised_psds,1),marker=markers.CARETLEFTBASE,color='r')
    ax.scatter(centralised_frequencies,np.min(centralised_psds,1),marker=markers.TICKLEFT,color='r')
    ax.scatter(centralised_frequencies,np.max(centralised_psds,1),marker=markers.TICKLEFT,color='r')
    ax.scatter(distributed_frequencies,np.mean(distributed_psds,1),marker=markers.CARETRIGHTBASE,color='b')
    ax.scatter(distributed_frequencies,np.min(distributed_psds,1),marker=markers.TICKRIGHT,color='b')
    ax.scatter(distributed_frequencies,np.max(distributed_psds,1),marker=markers.TICKRIGHT,color='b')
    
    ax.legend(*zip(*labels))
    ax.set_xlabel("Frequency (Hz)")
    ax.set_ylabel("PSD*Freq")
    ax.set_xlabel("Frequency (Hz)")
    ax.set_ylabel("PSD*Freq")
    ax.set_title("Centralised Control")
    ax.set_title("Distributed Control")
    fig.savefig("6_Results/clean_data/psd.png")
    plt.clf()
    plt.close()
问题原因
  1. x轴位置不匹配:violinplot默认的小提琴位置是从1开始的整数序列(1、2、3...),但散点图使用实际的frequency数值作为x坐标,导致x轴范围被拉宽,小提琴图被挤压到左侧区域。
  2. 重复设置轴属性:两次调用set_xticklabels、set_xlabel、set_ylabel、set_title,后一次会覆盖前一次的设置,造成无效操作。
解决方法

步骤1:统一小提琴图与散点图的x轴位置

假设centralised_frequencies和distributed_frequencies的数值完全一致(双小提琴对应同一频率位置),调用violinplot时指定positions参数为频率值,让小提琴图的位置与散点图的x坐标对齐。

步骤2:清理重复的轴设置

删除重复的set_xlabel、set_ylabel、set_title调用,保留一次正确设置。

修正后的代码

import matplotlib.pyplot as plt
import matplotlib.markers as markers
import numpy as np

# 假设add_label是你定义的用于给小提琴图添加图例的函数
labels = []
def add_label(violin, label):
    color = violin['bodies'][0].get_facecolor().flatten()
    labels.append((plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=color, markersize=10), label))

def plot_psd(centralised_frequencies,centralised_psds,distributed_frequencies,distributed_psds):
    # 确保两个频率数组一致,否则双小提琴无法对应同一位置
    assert np.array_equal(centralised_frequencies, distributed_frequencies), "频率数组必须一致"
    
    fig, ax = plt.subplots(1,1,figsize=(10,5))
    
    # 绘制中央控制的小提琴图,指定positions为频率值
    add_label(ax.violinplot(centralised_psds, positions=centralised_frequencies, side='high', 
                            showmeans=False, showmedians=False, showextrema=False), "Centralised Control")
    # 绘制分布式控制的小提琴图,使用相同的positions
    add_label(ax.violinplot(distributed_psds, positions=distributed_frequencies, side='low', 
                            showmeans=False, showmedians=False, showextrema=False), "Distributed Control")
    
    # 设置x轴刻度标签
    ax.set_xticks(centralised_frequencies)
    ax.set_xticklabels(centralised_frequencies)
    
    # 绘制散点标记:均值、最值
    # 中央控制相关标记
    ax.scatter(centralised_frequencies, np.mean(centralised_psds,1), marker=markers.CARETLEFTBASE, color='r')
    ax.scatter(centralised_frequencies, np.min(centralised_psds,1), marker=markers.TICKLEFT, color='r')
    ax.scatter(centralised_frequencies, np.max(centralised_psds,1), marker=markers.TICKLEFT, color='r')
    # 分布式控制相关标记
    ax.scatter(distributed_frequencies, np.mean(distributed_psds,1), marker=markers.CARETRIGHTBASE, color='b')
    ax.scatter(distributed_frequencies, np.min(distributed_psds,1), marker=markers.TICKRIGHT, color='b')
    ax.scatter(distributed_frequencies, np.max(distributed_psds,1), marker=markers.TICKRIGHT, color='b')
    
    # 设置图例、轴标签和标题
    ax.legend(*zip(*labels))
    ax.set_xlabel("Frequency (Hz)")
    ax.set_ylabel("PSD*Freq")
    ax.set_title("Centralised vs Distributed Control PSD Comparison")
    
    fig.savefig("6_Results/clean_data/psd.png")
    plt.clf()
    plt.close()

额外说明

如果你的centralised_frequencies和distributed_frequencies是不同的分类(非同一频率对比),则需要调整小提琴图的位置为连续整数,同时将散点图的x坐标替换为对应的整数索引,再设置xticklabels为频率值。例如:

# 生成整数位置
positions = np.arange(1, len(centralised_frequencies)+1)
# 小提琴图使用positions
ax.violinplot(centralised_psds, positions=positions, side='high', ...)
# 散点图x坐标用positions
ax.scatter(positions, np.mean(centralised_psds,1), ...)
# 设置刻度标签
ax.set_xticks(positions)
ax.set_xticklabels(centralised_frequencies)

内容的提问来源于stack exchange,提问作者Zedonkay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:00:13