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

如何从PwrAnalysis父类继承返回值并在PwrPlots子类中绘图?

解决子类继承父类并绘图的问题

我来帮你搞定这个问题,咱们一步步修正代码,让子类既能继承父类的全部参数,又能调用父类方法获取数据完成绘图:

首先,修正父类里的一个小bug

你的父类pwr_vs_effct_sz方法里,两个循环都把结果加到了pwr_vs_effect_size_2里,第一个循环应该对应pwr_vs_effect_size_1,修正后的父类代码:

from statsmodels.stats.power import FTestAnovaPower
class PwrAnalysis:
    def __init__(self, effect_size=None, nobs=None, alpha=None, alpha2=None, power=None, k_groups=None, rng1=None, rng2=None):
        self.effect_size = effect_size
        self.nobs = nobs
        self.alpha = alpha
        self.alpha2 = alpha2
        self.power = power
        self.k_groups = k_groups
        self.rng1 = rng1
        self.rng2 = rng2

    def pwr_vs_smpl_sz(self):
        pwr_vs_smpl_1 = []
        pwr_vs_smpl_2 = []

        for pwr_rng in self.rng1:
            pwr_vs_smpl_1.append(FTestAnovaPower().solve_power(effect_size=self.effect_size,
                                        nobs=None, alpha=self.alpha, power=pwr_rng, k_groups=self.k_groups))
        
        for pwr_rng in self.rng2:
            pwr_vs_smpl_2.append(FTestAnovaPower().solve_power(effect_size=self.effect_size,
                                        nobs=None, alpha=self.alpha2, power=pwr_rng, k_groups=self.k_groups))
        
        return  [pwr_vs_smpl_1, self.rng1], [pwr_vs_smpl_2, self.rng2]

    def pwr_vs_effct_sz(self):
        pwr_vs_effect_size_1 = []
        pwr_vs_effect_size_2 = []
        
        # 修正这里:第一个循环往pwr_vs_effect_size_1添加数据
        for pwr_rng in self.rng1:
            pwr_vs_effect_size_1.append(FTestAnovaPower().solve_power(effect_size=None,
                                        nobs=self.nobs, alpha=self.alpha, power=pwr_rng, k_groups=self.k_groups))
        for pwr_rng in self.rng2:
            pwr_vs_effect_size_2.append(FTestAnovaPower().solve_power(effect_size=None,
                                        nobs=self.nobs, alpha=self.alpha2, power=pwr_rng, k_groups=self.k_groups))
        
        return  [pwr_vs_effect_size_1, self.rng1], [pwr_vs_effect_size_2, self.rng2]
            
    def smpl_sz_vs_effct_sz(self):
        sample_size_vs_effect_size_1 = []
        sample_size_vs_effect_size_2 = []
        
        for num_of_smpls in self.rng1:
            sample_size_vs_effect_size_1.append(FTestAnovaPower().solve_power(effect_size=None,
                                        nobs=num_of_smpls, alpha=self.alpha, power=self.power, k_groups=self.k_groups))
        for num_of_smpls in self.rng2:
            sample_size_vs_effect_size_2.append(FTestAnovaPower().solve_power(effect_size=None,
                                        nobs=num_of_smpls, alpha=self.alpha2, power=self.power, k_groups=self.k_groups))        
            
        return  [sample_size_vs_effect_size_1, self.rng1], [sample_size_vs_effect_size_2, self.rng2]

然后,修正子类的核心问题

子类的主要问题有两个:一是__init__方法没有把参数传给父类,二是没有正确调用父类方法获取返回值。修正后的子类代码:

import matplotlib.pyplot as plt

class PwrPlots(PwrAnalysis):
    def __init__(self, effect_size=None, nobs=None, alpha=None, alpha2=None, power=None, k_groups=None, rng1=None, rng2=None):
        # 关键:把子类接收的所有参数传给父类构造方法,这样父类的属性才能正确初始化
        super().__init__(effect_size=effect_size, nobs=nobs, alpha=alpha, alpha2=alpha2, 
                         power=power, k_groups=k_groups, rng1=rng1, rng2=rng2)

    def plt_pwr_vs_smpl(self):
        # 调用父类方法获取返回数据
        data1, data2 = self.pwr_vs_smpl_sz()
        # 提取数据:data1是[样本量列表, 功效范围],data2同理
        sample_sizes1, powers1 = data1
        sample_sizes2, powers2 = data2

        # 绘制两条曲线,用不同颜色标记区分alpha值
        plt.plot(powers1, sample_sizes1, 'b', marker='o', label=f'alpha={self.alpha:.2f}')
        plt.plot(powers2, sample_sizes2, 'r', marker='s', label=f'alpha={self.alpha2:.2f}')
        
        # 添加图表元素
        plt.title('Power vs Sample Size')
        plt.xlabel('Power')
        plt.ylabel('Sample Size Required')
        plt.legend(loc="lower right")
        plt.grid(True)
        plt.show()

    def plt_pwr_vs_effct_sz(self):
        # 调用父类方法获取数据
        data1, data2 = self.pwr_vs_effct_sz()
        effect_sizes1, powers1 = data1
        effect_sizes2, powers2 = data2

        plt.plot(powers1, effect_sizes1, 'b', marker='o', label=f'alpha={self.alpha:.2f}')
        plt.plot(powers2, effect_sizes2, 'r', marker='s', label=f'alpha={self.alpha2:.2f}')
        
        plt.title('Power vs Effect Size')
        plt.xlabel('Power')
        plt.ylabel('Effect Size Required')
        plt.legend(loc="lower right")
        plt.grid(True)
        plt.show()

    def plt_smpl_sz_vs_effct_sz(self):
        # 调用父类方法获取数据
        data1, data2 = self.smpl_sz_vs_effct_sz()
        effect_sizes1, sample_sizes1 = data1
        effect_sizes2, sample_sizes2 = data2

        plt.plot(sample_sizes1, effect_sizes1, 'b', marker='o', label=f'alpha={self.alpha:.2f}')
        plt.plot(sample_sizes2, effect_sizes2, 'r', marker='s', label=f'alpha={self.alpha2:.2f}')
        
        plt.title('Sample Size vs Effect Size')
        plt.xlabel('Sample Size')
        plt.ylabel('Effect Size Required')
        plt.legend(loc="upper right")
        plt.grid(True)
        plt.show()

关键改动说明

  • 子类初始化:super().__init__不再硬传None,而是把子类接收的所有参数原样传给父类,这样父类的所有属性都会被正确初始化,子类自然支持父类的全部参数。
  • 获取父类数据:通过self.pwr_vs_smpl_sz()调用父类方法(子类继承了父类,直接用self调用即可,不需要super()),拿到返回的数据集后再提取需要的x、y轴数据。
  • 绘图逻辑:根据父类返回的数据结构,正确匹配x轴和y轴,同时给两条曲线设置不同的颜色和标记,方便区分不同alpha值的结果。
  • 父类bug修复:修正了pwr_vs_effct_sz方法中循环变量的错误,确保两组数据分别存入对应的列表。

测试示例

你可以这样测试代码:

# 创建子类实例,传入必要参数
pwr_plotter = PwrPlots(effect_size=0.5, alpha=0.05, alpha2=0.1, k_groups=3,
                       rng1=[0.7, 0.8, 0.9], rng2=[0.7, 0.8, 0.9])
# 绘制Power vs Sample Size图
pwr_plotter.plt_pwr_vs_smpl()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:15:35