外观
熵值法综合指标
熵值法客观赋权:极差标准化(区分正 / 负向指标)→ 比重
核心代码
py
def build_entropy_index(
*,
df: pd.DataFrame,
params: dict[str, Any],
column_descriptions: dict[str, str],
) -> tuple[pd.DataFrame, dict[str, Any], list[str], dict[str, str]]:
"""熵值法综合指标。"""
indicators = require_numeric_columns(df, normalize_string_list(params.get('columns')), label=_('指标变量'))
new_name = ensure_new_column_absent(df, params.get('new_name') or 'entropy_score')
directions = params.get('directions') if isinstance(params.get('directions'), dict) else {}
working, valid_columns, warnings = _prepare_indicator_frame(
df=df,
indicators=indicators,
missing_strategy=str(params.get('missing_strategy') or 'drop').strip().lower(),
standardize=False,
)
normalized = pd.DataFrame(index=working.index)
removed_columns = []
for column in valid_columns:
series = working[column]
maximum = series.max()
minimum = series.min()
if maximum == minimum:
removed_columns.append(column)
continue
direction = str(directions.get(column) or 'positive').strip().lower()
if direction == 'negative':
normalized[column] = (maximum - series) / (maximum - minimum)
else:
normalized[column] = (series - minimum) / (maximum - minimum)
normalized = normalized.drop(columns=removed_columns, errors='ignore')
if normalized.empty:
raise DataProcessingValidationError(_('所有指标都没有有效波动,无法计算熵值法'))
if removed_columns:
warnings.append(_('以下指标为常数列,已自动剔除: %(columns)s') % {'columns': ', '.join(removed_columns)})
adjusted = normalized.replace(0, 1e-12)
probability = adjusted.div(adjusted.sum(axis=0), axis=1)
sample_size = len(probability)
entropy_coefficient = 1.0 / np.log(sample_size) if sample_size > 1 else 0.0
entropy = -(probability * np.log(probability)).sum(axis=0) * entropy_coefficient
divergence = 1 - entropy
if divergence.sum() == 0:
raise DataProcessingValidationError(_('熵值法权重无法计算,所有指标信息量都为 0'))
weights = divergence / divergence.sum()
scores = normalized.mul(weights, axis=1).sum(axis=1)
result_df = df.copy()
result_df[new_name] = np.nan
result_df.loc[scores.index, new_name] = scores
descriptions = dict(column_descriptions)
descriptions[new_name] = _('熵值法综合得分')
details = {
'created_column': new_name,
'weights': {column: round(float(value), 6) for column, value in weights.items()},
'entropy': {column: round(float(value), 6) for column, value in entropy.items()},
'directions': {
column: str(directions.get(column) or 'positive').strip().lower()
for column in normalized.columns
},
'removed_constant_columns': removed_columns,
'score_summary': _build_score_summary(scores),
'score_histogram': _build_histogram(scores),
'used_columns': list(normalized.columns),
}
return result_df, details, warnings, descriptions极小样本复现
样本 entropy_indicators.csv 共 30 行 × 5 项指标(ind5 为负向指标)。
bash
python examples/run_entropy.py期望输出:
============================================================
熵值法综合指标(5 项指标,ind5 负向)
============================================================
样本量 N = 30
------------------------------------------------------------
指标 权重 熵值
ind1 0.141727 0.968064
ind2 0.273399 0.938394
ind3 0.1797 0.959507
ind4 0.123396 0.972195
ind5 0.281778 0.936505
------------------------------------------------------------
权重合计 = 1.000000
得分范围: 0.283177 ~ 0.826239