3. ESG数据清洗与预处理:缺失值处理、异常值检测、数据标准化与归一化、文本数据清洗(NLP基础)

各位同学,欢迎来到第三章。说实话,ESG分析里最磨人的不是建模,而是数据清洗。我见过太多人,模型跑得飞起,结果因为数据没洗干净,最后结论全是错的。这一章,咱们就把这些脏活累活讲透。

核心观点:ESG数据质量直接决定模型上限。再牛的算法,也救不了垃圾数据。

ESG数据清洗与预处理知识体系 ESG原始数据 缺失值处理 删除 | 均值填充 | 模型预测 异常值检测 IQR | Z-Score | 业务规则 标准化与归一化 Z-score | Min-Max 文本数据清洗(NLP) 分词 | 去停用词 | 词向量 清洗后的ESG数据

3.1 缺失值处理——别让空值毁了你的模型

ESG数据里,缺失值简直家常便饭。我做过一个项目,某公司碳排放数据缺了40%,你说这怎么整?

我个人习惯,先分三类情况处理:

  • 随机缺失:比如某年忘了填报告,这种可以用均值或中位数填充
  • 系统缺失:比如小公司根本不披露某些指标,这种得用模型预测
  • 完全缺失:整个行业都不披露,嗯,直接删掉这列吧

我的经验:千万别一上来就删数据。我曾经删掉一批缺失行,结果发现那些全是高污染企业,模型直接偏了。先分析缺失模式,再动手。

# 缺失值处理示例
import pandas as pd
import numpy as np
from sklearn.impute import KNNImputer

# 加载ESG数据
df = pd.read_csv('esg_data.csv')

# 查看缺失情况
print(df.isnull().sum())

# 数值型:用中位数填充(抗异常值)
df['carbon_emission'] = df['carbon_emission'].fillna(df['carbon_emission'].median())

# 分类型:用众数填充
df['disclosure_level'] = df['disclosure_level'].fillna(df['disclosure_level'].mode()[0])

# 高级玩法:KNN填充(适合有规律缺失)
imputer = KNNImputer(n_neighbors=5)
df_imputed = pd.DataFrame(imputer.fit_transform(df.select_dtypes(include=[np.number])))

3.2 异常值检测——揪出那些离谱的数据

ESG数据里异常值特别多。你想想看,一家制造业公司,碳排放突然比去年高了100倍,这合理吗?

我常用的方法就三个:

方法 适用场景 我的评价
IQR(四分位距) 数据分布偏态明显 简单粗暴,够用
Z-Score 数据近似正态分布 标准化后好比较
业务规则 有行业标准 最靠谱,但费功夫

避坑指南:我曾经用Z-Score一刀切,结果把某家新能源公司的高增长数据当异常删了。后来发现人家确实在扩产。记住:异常≠错误,可能是业务真相。

# 异常值检测实战
from scipy import stats

# IQR方法
Q1 = df['water_usage'].quantile(0.25)
Q3 = df['water_usage'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['water_usage'] < lower_bound) | (df['water_usage'] > upper_bound)]

# Z-Score方法
z_scores = np.abs(stats.zscore(df['employee_turnover']))
df_clean = df[(z_scores < 3)]  # 保留3个标准差内的数据

3.3 数据标准化与归一化——让不同量纲的数据能打架

ESG指标五花八门,碳排放是吨,员工流失率是百分比,董事会独立性是人数。你直接放一起算,那不是扯淡吗?

标准化和归一化,说白了就是让这些数据站在同一起跑线上。

  • Z-score标准化:适合数据有异常值的情况,把数据变成均值为0、标准差为1
  • Min-Max归一化:把数据压缩到[0,1]区间,适合神经网络

我的建议:做ESG评级模型,优先用Z-score。为什么?因为Min-Max对异常值太敏感,一个极端值就能把其他数据压成一条线。

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Z-score标准化(推荐)
scaler = StandardScaler()
df_scaled = pd.DataFrame(
    scaler.fit_transform(df[['carbon_emission', 'water_usage', 'waste_recycling']]),
    columns=['carbon_emission', 'water_usage', 'waste_recycling']
)

# Min-Max归一化
minmax_scaler = MinMaxScaler()
df_normalized = pd.DataFrame(
    minmax_scaler.fit_transform(df[['board_independence', 'employee_satisfaction']]),
    columns=['board_independence', 'employee_satisfaction']
)

3.4 文本数据清洗——从ESG报告里挖出金子

ESG数据不全是数字。那些几百页的可持续发展报告,里面藏着大量信息。我做过一个项目,光年报就爬了2000份,全是PDF。

文本清洗的流程,我总结为四步:

  1. 去噪:去掉HTML标签、特殊符号、多余空格
  2. 分词:中文用jieba,英文用NLTK
  3. 去停用词:去掉"的"、"了"、"是"这类没意义的词
  4. 词向量化:把文字变成数字,比如TF-IDF或Word2Vec

避坑指南:我曾经直接拿原始文本跑模型,结果"环境"和"环保"被当成两个词。后来加了同义词替换,效果好了不少。ESG领域,术语统一特别重要。

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer

# 中文分词示例
text = "公司致力于减少碳排放,提升环境绩效"
words = jieba.lcut(text)
print(words)  # ['公司', '致力于', '减少', '碳排放', '提升', '环境', '绩效']

# TF-IDF向量化
corpus = [
    "公司减少碳排放",
    "提升员工福利",
    "加强董事会监督"
]
vectorizer = TfidfVectorizer(tokenizer=jieba.lcut)
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names_out())

3.5 数据清洗流水线——把一切串起来

实际项目中,你不会一步步手动操作。我习惯用Pipeline把整个流程串起来,这样可复现、可部署。

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer

# 定义不同列的处理方式
numeric_features = ['carbon_emission', 'water_usage']
categorical_features = ['industry', 'region']

preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numeric_features),
        ('cat', 'passthrough', categorical_features)  # 分类列先不动
    ])

# 构建完整流水线
pipeline = Pipeline([
    ('preprocessor', preprocessor),
    # 后面再接模型...
])

# 一键清洗
df_clean = pipeline.fit_transform(df)

核心要点:数据清洗不是一次性工作。每次拿到新数据,都要重新审视清洗策略。我见过太多人,写了个清洗脚本就再也不管了,结果数据源一变,模型全崩。

好了,这一章的内容就到这。数据清洗确实枯燥,但它是整个ESG评级模型的基石。你想想看,如果数据都是脏的,后面的模型再花哨又有什么用?


专注资料整理