本文为学习黄晓林老师开设的慕课《探索数据的奥秘》所作笔记
数据科学简介
现时代科学范式正在转变,继实验、理论与计算之后,数据科学已成为人类探索世界的第四科学范式。工业界对数据科学的关注在应用层面,更关注相关性而非因果性。
数据
数据传感器采集到的各种物理、生物、化学指标等等可记录、可表征的数量、性质都是数据,对于行为的描述与记录也能构成数据,例如互联网上的一次次交易,访问。总之,现实中某种事物或事物间关系数量或性质的表征和记录,都称之为数据,数据是信息的载体。
大数据
有观点认为,当数据量大到需要使用并行计算工具处理时,就称之为大数据(Big Data)。通常认为大数据有4V特点,即体量大(High Volume)、速度快时效高(High Velocity)、类型繁多(High Variety)、价值密度低(High Veracity)
1993年,美国学者挨个拉沃提出了Aprior算法,可以通过分析购物篮中的商品几何,找出商品间关系,然后研究或推测顾客的购买行为,沃尔玛将其引入pos机数据分析,发现一些看似毫无关联的商品,例如啤酒和尿布经常出现在同一购物车中,即两者具有相关性。
数据科学
应用科学的方法、流程、算法和系统从多种形式的结构化或非结构化数据中提取知识和洞见的交叉学科。所有对数据的搜集,存储,分类,处理,分析,呈现都可纳入数据科学的范畴。
数据科学项目克可能涉及的人员:
人员 | 定位 |
---|---|
项目出资方 | 商业利益,提供项目支持 |
客户(或用户) | 最终用户利益(领域专家) |
数据架构师 | 管理数据和数据存储 |
运营工程师 | 管理基础设施和部署最终成果 |
数据科学家(核心人员) | 设定和执行分析战略 |
一、明确问题及制定目标
用户层面
针对用户的具体问题,应做好充足的背景调查,从而制定出相应的用户层面的目标。
数据科学层面:可将问题抽象为分类、预测、排名或打分、关联化、特征提取、聚类等。
类型 | 描述 |
---|---|
分类 | 对于给定的数据,依据一定的规则进行两个或两个以上的类别划分,输出为针对输入的数据所分配的类别标签。例如:真/假,类别A / 类别B / 类别C /… |
预测 | 基于一直数据对将来的状态作出估计或判断,输出为连续的数量值或类别标签 |
排名 (打分) | 对于实体的某种属性或响应进行数量化描述或进行排序 |
关联化 去关联化 | 在尸体的众多特征种,寻找有相互关联的特征以便相互替代,从而实现特征的相互“解释”或数据降维;而对于非关联的特征则需予以保留以实现对样本的全面描述 |
特征提取 | 基于实体的众多特征,构造最反应目标的,或最能知识某种分类的复合特征 |
聚类 | 根据样本间的相似度将样本分组 |
二、数据搜集与准备
前提假设和数据构成
明确必要的前提假设,基于假设的前提来设计数据的构成,明确总体和抽样方案再搜集数据。
在面向实际应用时,始终不能忘记方案的可行性分析,不同的假设很可能会涉及不同的数据,最终导致不同的研究内容。因此,在真正进行数据搜集之前,应认真审视与事实最符合的假设,根据最符合事实的假设提出对应的数据方案,思考方案的可行性,确定数据的构成。
通常,后续方便处理的数据是 ” 结构化 “ 的数据(可将其抽象的理解为一张二维表,一行对应一个样本,一列对应一个属性)
总体和抽样
总体(Population):待研究对象的全体
个体(Individual):总体中的每一个对象
样本:在无法获得总体的情况下,从总体中抽取出来的子集
样本容量:样本包含的个体数量
- 数据收集是一种从总体中抽样的过程
- 样本容量不能太小,传统统计学认为小于30的样本容量不具备统计学意义
- 抽样时不能有预设偏见,也就是必须无偏抽样,即抽样的过程不受个体性质的影响。
- 抽样偏差指从总体中非随机型抽样带来的系统性错误,幸存者偏差就是一种常见的抽样偏差
- 避免抽样偏差常见的作法是随机抽样。随机抽样是指总体中的个体是否被抽样并非是确定的(即,不因为个体的某个或某些性质一定被抽中或一定不被抽中),而是以一定的概率被抽样
混杂因素和A/B Testing
辛普森悖论: 人们尝试探究两种变量(比如新生录取率与性别)是否具有相关性的时候,会分别对之进行分组研究。然而,在分组比较中都占优势的一方,在总评中有时反而是失势的一方。
常见的排除混杂因素影响的做法: 对两相比较的样本集,做好潜在混杂因素(甚至所有非考察因素)的匹配。
- 对于关联任务而言,混杂因素的排除是关键
A/B Testing: 指专门设计一些对比试验,在其他所有特征都匹配(或一致)的情况下,只观察一个变量的不同取值对于结果的影响。科学研究中,在实验室的可控环境下,A/B Testing 是一种非常常见的实验手段,例如 “ 双盲实验 ” 。主动搜集数据时,A/B Testing 是一种可靠而有效的方式。
三、使用python进行数据导入
NumPy.load_txt()
- 将指定文件中的数据加载到数组
- 支持纯文本文件,如 txt 文件和 csv 文件
- 返回 NumPy 的 ndarray 多维数组
- 一般用来加载数据类型一直的数据文件
import numpy as np
x = np.loadtxt('E:\my_data.csv', delimiter=',')
#查看导入数据的规模
print(x.shape)
#ndarray的二维切取
x[:2,:3]
#指定导入的数据类型为int
x_int = np.loadtxt('E:\my_data.csv', delimiter=',', dtype=int)
Pandas.read_csv()
- 面对数据并不统一的电子表格数据
- 将电子表格文件中的数据导入到 Pandas 的 DataFrame 结构(二维表格结构)
import pandas as pd
#header=None表示没有表头
#names参数:为表格的各列设置列标题
data = pd.read_csv('E:\my_data.csv,
header=None, names=['A','B','C','D','E'])
#可以使用data.values访问表格中存放的数据,为ndarray类型
print(data.values)
Python自带模块urllib 可用于网上在线获取文件
- urllib.request.urlopen()
CountVectorizer实现非结构化数据转化为结构化数据
非结构化数据一般通过结构化处理使其成为表格,方便后续的分析与建模
#使用fetch_20newsgroups函数可以自动下载数据到
#[Currentuser]\scikit_learn_data 下面
from sklearn.datasets import fetch_20newsgroups
#下载医学新闻数据集
my_news=fetch_20newsgroup(categories['sci.med'])
print(twenty_sci_news_data[0], '\n')
#CountVectorizer是属于常见的特征数值计算类,是一个文本特征提取方法
#对于每一个训练文本,它只考虑每种词汇在该训练文本中出现的频率。
from sklearn.feature_extraction.text import CountVectorizer
count_vect=CountVectorizer()
#通过fit_transform函数计算各个词语出现的次数,返回一个稀疏矩阵对象
word_count=count_vect.fittransform(my_news.data)
对大规模数据的读取
- 以连续流的方式流入,而非一次性加载
import pands as pd
#规定chunksize后返回的数据类型不再是DataFrame
#而是一个可迭代的TextFileReader对象
#它保存了若干个chunk的尺寸和位置
#但只有当被迭代器指到时,才会真正把对应的数据读入内存
my_chunk=pd.read_csv('E:\my_data.csv', header=None,
names=['A','B','C','D','E'],
chunksize=20)
for n,chunk in enumerate(my_chunk):
print(chunk.shape)
if n <= 2:
print(chunk) #每一个chunk都是一个DataFrame
print('\n')
#get_chunk()方法是当前位置获取指定大小的数据块
#会改变迭代器指针
#if n <= 2:
# print(my_chunk.get_chunk(1),'\n')
- csv 包中的 reader 函数和 DictReader 函数 可以实现小块数据的迭代
import numpy as np
import pandas as pd
import csv
#with命令保证以下代码执行完后文件会关闭
with open('E:\my_data.csv', 'r') as my_data_stream:
#用csv.reader读取文件,一次读取一行,作为列表对象
my_reader=csv.reader(my_data_stream,dialect='excel')
for n,row in enumrate(my_reader)"
if n <= 5:
print(row, '\n')
四、探索性数据分析(EDA)
- 初步了解数据集
- 验证初步假设
数据检查和预处理
- 数据检查 :数据的规模与特征的数据类型及意义
- 预处理:缺失处理、异常处理、冗余处理
数据的类型:数值型数据、字符型数据、逻辑型数据(bool型数据)、排序类型
(依据某个量度得到的,具备一定的量化意义)
对于数值型数据,可以用算术平均,标准差等量化统计量进行分析。
对于非数值型数据,主要依据它们进行分组与筛选。
数据的初步分析
- 缺失数据:用 NaN 表示
- 数据随机性缺失
- 直接丢弃:dataframe.dropna函数(样本容量大,缺失信息少)
- 修补填充:dataframe.fillna函数(样本容量小,无法承受进一步缺失) 缺失值填充是一种止损手段,可以将原本不完整数据行中的其他信息利用起来,从而避免了有效信息的进一步损失。
- 非随机性缺失:具体情况具体分析
- 数据混则了噪声、干扰,甚至错误数据。应基于数据的实际意义,利用常识或专业领域知识进行判断。
my_dict={'A':'1','B','2'} #A列填充为1,B列填充为2
my_fill_data3=my_data.fillna(my_dict)
my_fill_data4=my_data.fillna(method='ffill) #使用缺失值之前的邻近值进行填充
my_fill_data4=my_data.fillna(method='bfill) #使用缺失值之后的邻近值进行填充
- 对于服从正态分布的数据:z-score
z-score 是个无量纲的数,可以消除数据本身的取值范围带来的影响。一般认为z-score > 3 时,可以怀疑异常。 - 对于不服从正态分布的数据:四分位距
q1:第一个四分位数
q3:第三个四分位数
△ = q3 - q1:四分位距
x > q3 + 3△ 或 x < q1 - 3△:认为是极端异常值或离群值outlier - 对于异常值
情况 | 处理方法 |
---|---|
确定是出错的数据 | 丢弃或替换 |
不能肯定是错误 | 增加样本容量 |
- 数据冗余
情况 | 处理方法 |
---|---|
数据列直接重复 | 直接通过列名称或特征名筛选 |
不同特征出现冗余 | 如果一个特征可以通过将另一个线性特征变换得到,那么这两个特征就是重复的,可以去掉一个。 |
判断特征冗余常用方法:线性相关分析
Dataframe.corr函数
当参数 method=‘pearson’ 时,直接求线性相关系数
- 线性相关系数接近 1 或 -1 ,则说明两个特征存在强的线性相关或反相关,有着较大的冗余
- 线性相关系数等于 0, 两个特征间没有线性相关性
描述性统计
描述性统计不对数据做任何预先地猜想,实事求是地告诉我们样本数据是怎样的。在描述性的结果上进行思考可以形成一些初步的结论。
- 位置性测度计算
位置性测度主要用来反映样本集合的中心成员或特定成员在所考察的数域或空间的位置。只能针对数值数据计算。
常用的位置测度 | 定义 | 特点 | 函数 |
---|---|---|---|
算术平均(arithmetic mean) | 对所有考察的样本值求统计平均 | 易受极端值影响 | dataframe.mean() |
中位数(median) | 将所有样本按数值从小到大或从大到小排序后,最中间位置的一个数,或者两个数的平均 | 对极端值不敏感,但对中位数以外的所有值也都不敏感 | dataframe.median() |
p 百分位数(quantiles) | 将所有样本值按从小到大的顺序拍好,排序在第 p% 的样本取值 | 第 p 个百分位数记为 Vp,则样本中有且仅有 p% 的观察值小于等于 Vp | dataframe.quantiles(q=0.25) |
众数(mode) | 样本集中出现次数最多的值 | 众数可能只有一个,也可能有多个 | dataframe.mode() |
常用的 p 百分位数:
- 第10百分位数
- 第25百分位数(第一四分位数)
- 第50百分位数(中位数)
- 第75百分位数(第三四分位数)
- 第90百分位数
- 离散性测度计算
只能针对数值数据计算
常用离散性测度 | 描述 | 函数 |
---|---|---|
极差(range) | 指集合中最大与最小值之间的差异,对极端值非常敏感 | max() - min() |
方差(variance) | 对集合中所有样本值相对于均值的偏差的平方求近似平均 | var() |
标准差(Standard Deviation) | 方差的平方根称为标准差,方差和标准差可以总体衡量集合中数据偏离均值的程度 | std() |
变异系数(coefficient of variation, CV) | 无量纲,能尽量消除单位及均值的绝对位置带来的影响。 | std() / mean() |
describe函数:对dataframe中所有用数值保存的特征(无论是整数还是浮点数),一次性计算多个常用的描述性统计量
- 图形化描述
既适用于数值型数据,也适用于非数值型数据的计算
常用图形 | 描述 | 函数 |
---|---|---|
直方图 | 将数据分组,记录样本在每个组中出现的频数 | hist函数 |
箱型图 | 通过几个重要的百分位数来界定数据的主要分布,下边缘为 q1,上边缘为 q3,箱子的中线代表中位数,箱子两端伸出的虚线用来刻画极差,超出上下边缘的被当作异常值或outlier离群点 | boxplot函数 |
-
非数值型的特征
主要应用来分组,从而对各组进行频次统计,绘制与直方图类似的柱状图
利用 dataframe.groupby 函数进行分组 -
两个数值型特征相结合
简单的图形化方法为二维散点图,其绘制方法为: 用样本在一个特征上的取值作为横轴,在另一个要关联考察的特征上的取值作为纵轴,这样在二维平面上确定下该样本的位置,描绘出一个样本点。
可以采用 pandas.plotting.scatter_matrix 对两个数值型特征绘制散点图。
统计建模(统计推断)
实质:由样本去推断总体的过程
主要包括:参数估计和假设检验
import numpy as np
import pandas as pd
from scipy import stats
np.random.seed(1234)
#生成一个规定均值的泊松分布
my_data1=stats.poisson.rvs(loc=10,mu=60,size=3000)
pd.Series(my_data1).hist().get_figure().show
my_data2=stats.poisson.rvs(loc=10,mu=15,size=6000)
pd.Series(my_data2).hist().get_figure().show
#生成一个典型的bi-mode分布,以这9000个数据作为总体
my_data=np.comcatemate(my_data1, my_data2)
#随机抽取100个作为样本
sample_data=np.random.choice(a=my_data,size=100)
sample_size=100
sample=np.random.choice(a=my_data,size=sample_size)
sigma=sample.std()/(sample_size)**0.5
stats.t.interval(alpha=0.95, #置信水平
df=sample_size-1,
loc=sample.mean(),
scale=sigma)
假设检验
- 提出假设
- 验证是否可以接受假设
零假设(null hypothesis):H0,需要检验的假设,如:
- 总体的均值等于μ
- 测试组和对照组来源于均值相等的总体
- 控制因素对观察变量有没有影响,A组和B组数据同分布
替代假设(alternative hypothesis):H1,某种程度上与 H0 相反的假设。
from scipy.stats import t