外观
分组描述统计
按分组变量分别计算各组的描述统计量。
核心代码
py
def _fit_grouped_descriptive(self, df: pd.DataFrame, decimals: int, title: str) -> None:
"""
执行分组描述性统计分析
参数:
df: 数据框
decimals: 小数位数
title: 表格标题
"""
if not self.group_var:
raise ValueError(_('未指定分组变量。'))
if self.group_var not in df.columns:
raise ValueError(_('分组变量 %(var)s 不存在于数据中。') % {'var': self.group_var})
# 检查分析变量
target_cols = self.x_vars
if not target_cols:
raise ValueError(_('未选择任何分析变量。'))
# 筛选数值列
valid_cols = [c for c in target_cols if c in df.columns]
numeric_cols = [c for c in valid_cols if df[c].dtype in [np.float64, np.float32, np.int64, np.int32]]
if not numeric_cols:
raise ValueError(_('没有可用的数值型变量进行描述性统计。'))
# 只删除分组变量的缺失值,保留分析变量的缺失值
df_clean = df[[self.group_var] + numeric_cols].dropna(subset=[self.group_var])
if df_clean.empty:
raise ValueError(_('清洗后的数据为空。'))
# 按分组变量分组计算描述性统计
grouped = df_clean.groupby(self.group_var)
# 为每个分组构建独立的结果表格
group_tables = []
for group_name, group_data in grouped:
group_results = []
for var in numeric_cols:
# 对每个变量单独处理缺失值
var_data = group_data[var].dropna()
row_dict = {'Variable': var}
# 如果该变量在该分组中全是缺失值,只显示N=0,其他统计量不显示
if len(var_data) == 0:
if 'nobs' in self.desc_options or 'count' in self.desc_options:
row_dict['N'] = 0
# 其他统计量设置为空字符串(不显示)
if 'mean' in self.desc_options:
row_dict['Mean'] = ''
if 'std' in self.desc_options:
row_dict['Std.Dev'] = ''
if 'min' in self.desc_options:
row_dict['Min'] = ''
if 'max' in self.desc_options:
row_dict['Max'] = ''
if 'p50' in self.desc_options:
row_dict['Median'] = ''
else:
# 有有效数据,正常计算统计量
if 'nobs' in self.desc_options or 'count' in self.desc_options:
row_dict['N'] = len(var_data)
if 'mean' in self.desc_options:
row_dict['Mean'] = var_data.mean()
if 'std' in self.desc_options:
row_dict['Std.Dev'] = var_data.std()
if 'min' in self.desc_options:
row_dict['Min'] = var_data.min()
if 'max' in self.desc_options:
row_dict['Max'] = var_data.max()
if 'p50' in self.desc_options:
row_dict['Median'] = var_data.median()
group_results.append(row_dict)
# 如果该分组有有效数据,添加到结果中
if group_results:
group_df = pd.DataFrame(group_results)
group_tables.append({
'group_name': str(group_name),
'data': group_df
})
# 生成HTML(竖式布局,每个分组一个表格)
title = title if title else f"Grouped Descriptive Statistics by {self.group_var}"
self.custom_html = self._generate_grouped_descriptive_html_vertical(
group_tables, title, decimals, self.group_var
)