如何从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
相关产品推荐
相关产品推荐

