import pandas as pd
df = pd.DataFrame({
"性别": ["男", "女", "女", "男"],
"学历": ["本科", "硕士", "博士", "本科"]
})
print(df)
性别 学历
0 男 本科
1 女 硕士
2 女 博士
3 男 本科
在数据科学中,探索性数据分析 (EDA) 是一种用于分析数据集以总结其主要特征的技术,通常使用可视化方法。EDA 是数据分析过程中的一个重要步骤,因为它可以帮助我们了解数据的结构、分布和潜在的关系。
EDA 通常在数据建模之前进行,以便为后续的建模和分析提供基础。它可以帮助我们识别数据中的模式、趋势和异常值,从而为后续的分析提供指导。 EDA 的主要目标是:
EDA 通常包括以下步骤:
在进行统计建模之前,我们通常要先对数据有一个全面的了解,这一步就叫做 探索性数据分析 (exploratory data analysis, EDA)。EDA 的目的不是做推断,而是通过图形和汇总统计等手段,对数据的结构、变量的分布特征、变量之间的关系,以及观测值之间的聚集情况进行初步探索。
有些时候,我们并不清楚数据中有哪些信息,也还没想好要问什么问题,这时 EDA 可以帮助我们发现线索,启发思路。即便研究目标一开始就很明确,EDA 也仍然是不可跳过的环节。我们需要确认:
只有对数据的“样貌”做到心中有数,后续的建模和推断工作才可能稳妥有效。
在数据分析中,数值变量大致可以分为两类:分类变量 和 数值变量。
分类变量 (categorical variables):表示事物的类别属性,常见的如性别、地区、行业等。
数值变量 (numeric variables):表示数量大小,既包括取整数的变量,也包括可以取连续小数的变量。
准确判断变量类型,有助于我们选择恰当的图形展示方法与统计工具,是数据分析中的基本功之一。
我们日常接触到的数据,大多以表格形式存储,每一行是一个观测对象,每一列是一个变量。这类数据称为 结构化数据 (structured data),是数据分析中最常见的形式。
在结构化数据中,每一个变量(字段)通常表示一种特征或属性。根据变量的表现形式与分析方法,变量大致可以分为两类:分类变量 和 数值变量。除此之外,我们在实际项目中还会遇到 非结构化数据 和 半结构化数据,处理方式与建模策略也会有所不同,下面分别介绍。
分类变量表示对象所属的类别或属性,不直接反映数量大小。根据是否有顺序,可以进一步区分为两种:
import pandas as pd
df = pd.DataFrame({
"性别": ["男", "女", "女", "男"],
"学历": ["本科", "硕士", "博士", "本科"]
})
print(df)
性别 学历
0 男 本科
1 女 硕士
2 女 博士
3 男 本科
继续介绍「数字-文字对应表」,或字典的概念。 目的:便于存储,便于进行数值分析和分类操作
在数据分析中,使用数字-文字对应表(字典)可以将分类变量转换为数值变量,从而便于进行数值分析和分类操作。例如,将学历从“小学”、“初中”等文字形式映射为数字形式(如 1, 2, 3 等),可以方便地进行排序、统计和回归分析等操作。
这种映射方式的优点包括:
以下代码展示了如何通过字典将学历字段映射为对应的数值编码。
# 定义学历映射字典
education_mapping = {
"小学": 1,
"初中": 2,
"高中": 3,
"本科": 4,
"硕士": 5,
"博士": 6
}
# 将学历字段映射为数值编码
df["学历编码"] = df["学历"].map(education_mapping)
print(df)
性别 学历 学历编码
0 男 本科 4
1 女 硕士 5
2 女 博士 6
3 男 本科 4
数值变量表示数量大小,可以进行加减乘除等运算,通常又分为:
在下面的数据中,虽然三个变量都是数值型变量,但 月薪 通常被视为连续变量,满意度评分 则被视为离散型变量。至于 年龄,则需要根据具体情况来判断:如果年龄只取整数值且在样本中只有不多的几个取值,通常也被视为离散型变量;如果年龄可以取小数值或取值范围很大,则可以视为连续型变量。
此外,满意度评分 事实上具有两层含义:
3
分确实比 2
分高,4
分比 3
分高,因此它也可以作为数值变量来处理。半结构化数据 (semi-structured data) 介于结构化与非结构化之间。它没有固定表格格式,但可以通过规则解析提取信息,常见格式包括 JSON、XML、网页嵌入块等。
在实际项目中,金融与政府数据平台往往提供 API 接口或 JSON 格式数据。例如,某公司年报摘要的接口可能返回如下内容:
{
"company_name": "贵州茅台",
"stock_code": "600519",
"report_year": 2023,
"financials": {
"revenue": 1360.5,
"net_profit": 620.3
},
"industries": ["食品饮料", "白酒"],
"announcement_date": "2024-03-25"
}
这类数据可以方便地转化为结构化表格,常用 Python 代码如下:
import json
import pandas as pd
data = '''
{
"company_name": "贵州茅台",
"stock_code": "600519",
"report_year": 2023,
"financials": {
"revenue": 1360.5,
"net_profit": 620.3
}
}
'''
info = json.loads(data) # 解析JSON数据
# 打印解析后的数据
print("公司名称:", info["company_name"])
print("净利润:", info["financials"]["net_profit"], "亿元")
# 转换为数据框
df_info = pd.DataFrame([flat_info])
print('-'*50)
print(df_info)
公司名称: 贵州茅台
净利润: 620.3 亿元
--------------------------------------------------
公司名称 股票代码 报告年度 营业收入(亿元) 净利润(亿元)
0 贵州茅台 600519 2023 1360.5 620.3
这种数据结构非常适合用于系统对接、爬虫采集和接口开发,在财经信息系统中使用极为广泛。
还有些数据虽然表面上存储的很整齐,但也不是结构化数据。例如,网页中的嵌入式格式(如 HTML、Markdown 等)也可以看作半结构化数据。
非结构化数据 (unstructured data) 是指没有固定字段或列名的数据,最常见的是文本、图像、音频等。其中,金融研究中常见的非结构化数据包括公司公告、新闻、研报等自然语言文本。例如:
“本公司于 2023 年 6 月 1 日,与建行深圳分行签署贷款协议,贷款金额为 2 亿元,期限 3 年,利率为年化 4.2%。本次贷款以公司部分机器设备作抵押,由控股股东提供担保。若未能按期偿还,将触发违约条款。”
“经查,深圳市汇通科技股份有限公司在 2022 年年度报告中存在虚假记载。公司未如实披露其与下属子公司之间的关联交易情况,涉案金额累计达 1.38 亿元,相关资金部分已通过非正常渠道流出。上述行为违反了《证券法》第六十三条第一款的规定。根据《证券法》第二百二十三条的规定,我会决定:对深圳市汇通科技股份有限公司责令改正,给予警告,并处以 600 万元罚款;对时任董事长兼总经理李某某给予警告,处以 120 万元罚款,并采取 5 年市场禁入措施。有关当事人如对本处罚决定不服,可自收到本决定书之日起 60 日内向国务院申请行政复议,或自收到本决定书之日起 6 个月内依法向人民法院提起诉讼。”
今年发展主要预期目标是国内生产总值增长 5% 左右,城镇新增就业 1100 万人以上,居民消费价格涨幅在 3%-5% 之间,单位国内生产总值能耗持续下降。要围绕高质量发展这一首要任务,着力推动先进制造业、数字经济、生物医药等战略性新兴产业集群发展,提升现代化产业体系的韧性与安全性。
鼓励地方因地制宜发展新质生产力,继续实施新能源汽车下乡、智能家电换代等行动,推动重点领域设备更新和消费品以旧换新。坚持绿水青山就是金山银山,强化重点行业污染治理,推进钢铁、电解铝、水泥等行业节能降碳改造,加快构建以新能源为主体的新型电力系统。稳步推进碳达峰碳中和各项工作,推动形成绿色低碳的生产方式和生活方式。
在数据清晰阶段,我们要把「非结构化数据 (脏数据)」处理成「结构化数据 (整洁数据)」。
整洁数据 有三条核心原则 (Source: R for Data Science, Chap5):
此外,整洁数据还应遵循以下结构规范:
loan_amount
)或驼峰式命名(如 LoanAmount
),避免使用过短或含义不明的变量名。.
、NA
或 NULL
表示缺失,避免混用。假设世纪兴达公司 (股票代码:500288) 发布了一则贷款公告:
“本公司于 2023 年 6 月 1 日,与建行深圳分行签署贷款协议,贷款金额为 2 亿元,期限 3 年,利率为年化 4.2%。本次贷款以公司部分机器设备作抵押,由控股股东提供担保。若未能按期偿还,将触发违约条款。”
这段公告以文本段落呈现,信息分散,难以直接用于数据分析,属于典型的非结构化脏数据。我们需要将其中的关键信息提取并整理成结构化数据。
明确目标字段:目标字段包括贷款银行、贷款金额、贷款时间、利率、期限、是否有抵押、抵押品类型与描述、是否有担保、担保情况、违约条款等。
信息拆解与归类:
格式标准化:
缺失值处理:如公告未提及抵押品价值或担保方式,可设为“未披露”或留空,后续视业务需求再补全。
一位同学经过处理后,提取了如下信息:
字段 | 值 |
---|---|
银行名称 | 建行深圳分行 |
贷款金额 | 2 亿元 |
签署时间 | 2023 年 6 月 1 日 |
贷款期限 | 3 年 |
利率 | 4.2% |
是否有抵押品 | 是 |
是否有担保 | 是 |
违约条件 | 未能按期偿还 |
虽然处理后的数据已经比较规整了,但还没有达到「整洁数据」的要求。进一步处理后,我们可以得到如下表格:
字段 | 值 |
---|---|
公司名称 | 世纪兴达 |
股票代码 | 500288 |
银行名称 | 中国建设银行深圳分行 |
贷款金额 | 2000000000 |
货币单位 | 人民币 |
签署时间 | 2023-06-01 |
贷款期限(年) | 3 |
利率 | 0.042 |
是否有抵押品 | 是 |
抵押品类型 | 固定资产 |
抵押品名称 | 部分机器设备 |
是否有担保 | 是 |
担保人 | 控股股东 |
担保人类型 | 自然人/法人 |
违约条件 | 未能按期偿还 |
相比之下,更新后的表格做了如下修改:
当然,如果数据量比较大,可以删除“是否有抵押品”和“是否有担保”等字段,因为后续数据处理时可以通过“抵押品类型”和“担保人类型”来判断是否有抵押品和担保。另外,表中的布尔值(是/否)也可以用 0 和 1 来表示,一遍节省存储空间。
本例仅包含了一家公司的公告,实际分析中我们可能会遇到数万条公告。通常需要按如下流程处理:
这类任务称为 信息抽取 (information extraction),通常会使用自然语言处理 (NLP) 工具包(如 NLTK、spaCy、transformers 等)来实现。
以下是一个简单的示例,使用正则表达式从文本中提取贷款金额:
import pandas as pd
import re
# Variables from the notebook
text = '贷款金额为 2 亿元人民币,期限 3 年,利率为年化 4.2%。'
# 从文本中提取信息并创建数据框
# 提取贷款金额
if amount:
loan_amount = int(float(amount.group(1)) * 1e8) # 转换为元
else:
loan_amount = None
# 提取货币单位
currency = "人民币" # 假设货币单位为人民币
# 提取签署时间
sign_date = "2023-06-01" # 假设签署时间固定
# 提取贷款期限
if term:
loan_term = int(term.group(1))
else:
loan_term = None
# 提取利率
if rate:
interest_rate = float(rate.group(1)) / 100 # 转换为小数
else:
interest_rate = None
# 创建数据框
data = {
"字段": ["贷款金额", "货币单位", "签署时间", "贷款期限(年)", "利率"],
"值": [loan_amount, currency, sign_date, loan_term, interest_rate]
}
df_output = pd.DataFrame(data)
# 打印数据框
print(df_output)
字段 值
0 贷款金额 200000000
1 货币单位 人民币
2 签署时间 2023-06-01
3 贷款期限(年) 3
4 利率 0.042
不同数据类型的核心特征与处理策略如下:
数据类型 | 示例 | 特点与处理方式 |
---|---|---|
结构化数据 | Excel、CSV、DataFrame 表格 | 每列为变量,可直接分析建模 |
非结构化数据 | 公告文本、PDF、图像、音频 | 需先用 NLP 或图像处理方法进行结构化 |
半结构化数据 | JSON、XML、网页嵌入内容 | 用规则或工具解析后可转化为结构化形式 |
理解不同数据结构,是进入实际分析工作前的重要准备。后续章节中我们将围绕结构化数据展开建模分析,同时逐步引入处理半结构化与非结构化数据的方法。
缺失值是数据分析中常见的问题,处理缺失值的方法有很多,常用的方法包括: - 删除缺失值:直接删除包含缺失值的行或列 - 填充缺失值:使用均值、中位数、众数等方法填充缺失值 - 插值法:使用插值法估计缺失值 - 预测法:使用机器学习模型预测缺失值
异常值是指与其他数据点显著不同的观测值,处理异常值的方法有很多,常用的方法包括: - 删除异常值:直接删除包含异常值的行或列 - 替换异常值:使用均值、中位数、众数等方法替换异常值 - 转换异常值:使用对数变换、平方根变换等方法转换异常值 - 分箱法:将异常值分到其他类别中 - 使用机器学习模型预测异常值 - 使用聚类算法识别异常值
重复值是指数据集中存在多次重复的观测值,处理重复值的方法有很多,常用的方法包括: