探索性数据分析
本文记录2022年3月组队学习-动手学数据分析教程知识点,采用kaggle上泰坦尼克的任务,实战数据分析全流程。
教程内容开源地址:
github
: https://github.com/datawhalechina/hands-on-data-analysis
gitee
:https://gitee.com/datawhalechina/hands-on-data-analysis
1 第一章:数据载入及初步观察
数据集下载 https://www.kaggle.com/c/titanic/overview
1.1 导库
本次主要使用python的Pandas
库,numpy
库对结构化数据进行探索性研究。
import numpy as np
import pandas as pd
1.2 载入数据
知识点:
- 相对路径与绝对路径
相对路径
: 相对于当前文件的路径 注意./与…/区别 前者表示当前文件夹 后者表示上一级文件夹。绝对路径
: 当前文件在磁盘上真正存在的位置 。
一般使用相对路径避免因为文件位置变化而引起配置路径出现问题,需要注意绝对路径的划分符为"/"
。
- pandas读取数据函数read_csv与read_table
pandas
中读取数据函数为read开头,例如read_csv
与read_table
,read_csv
是pandas中读取以","
进行划分的数据,返回为DataFrame
表格类型结构。read_table
可以读取以制表符"\t"
进行划分的数据集,因此可以读取".tsv"结尾数据集等等。
二者本质没有较大区别,因划分符的不同而作用于不同的数据集,但我们可以通过指定str
参数指定当前数据集的划分符。
# 使用相对路径载入数据
train_data = pd.read_csv("train.csv")
test_data = pd.read_csv("test_1.csv")
# python自带库函数os 可以查询当前文件在系统中的绝对路径
import os
os.getcwd()
# 'E:\\python参考\\hands-on-data-analysis-master (1)\\hands-on-data-analysis-master\\第一单元项目集合'
# 使用绝对路径载入数据
train_data = pd.read_csv("E:/python参考/hands-on-data-analysis-master (1)/hands-on-data-analysis-master/第一单元项目集合/train.csv")
test_data = pd.read_csv("E:/python参考/hands-on-data-analysis-master (1)/hands-on-data-analysis-master/第一单元项目集合/test_1.csv")
# 指定划分符为","
pd.read_table("train.csv", ",")
- 大型数据集处理方法,设置
chunksize
参数
- 当遇到文件过大,导致内存不足时,可以先把整个文件拆分成小块(
chunk
), 一个chunk就是我们数据的一个小组.通过chunksize
参数可以指定我们迭代块的大小, 也可以通过设置iterator
参数(默认为False
)为True
后,通过迭代对象的get_chunk
方法迭代获得任意行。 chunk
块为dataframe
类型,每次for
循环输出就是chunk
大小的dataframe
表格。- 分块读取可以减少每次处理数据集的大小,加快运算时间,避免数据集过大无法读取或者读取过慢。
chunk = pd.read_csv("train.csv", chunksize=1000)
printg(chunk)
# <pandas.io.parsers.TextFileReader at 0x1538e1e33c8> 获得是一个可迭代对象 大小为chunksize值
for temp in chunk:
print(type(temp)) #DataFrame
# 获得到每个迭代对象为DataFrame对象
print(temp)
# 调用toString()方法打印表格
# 可以通过设置iterator参数获得可迭代对象
chunk_iterator = pd.read_csv("train.csv", iterator=True)
chunk_iterator.get_chunk(1000).shape
1.3 查看数据
知识点
- head() 与 tail() 函数
加载完数据一般我们都要查看一下数据情况,我们可以通过head()
与tail()
来观察具体情况。
head()
函数可以查看前k
行数据,默认为5
。tail()
函数可以观察倒数k
行数据, 默认为5
。- 需要注意
jupyter
展示行数是有限制的,需要通过配置set_option
中max_row
与max_columns
来设置。
# 观察前5行数据
train_data.head()
# 观察前10行数据
train_data.head(10)
# 观察倒数15行数据
train_data.tail(15)
- 查看数据的基本信息(缺失值,数据类型,数据形状,观察数据)
info()
函数查看数据集的缺失值、数据类型、数据形状describe()
函数查看数据集的观测数据(平均值,分位数等)isna()
、isnull()
与isnan()
查询缺失值函数 可以通过取和sum()
获得列缺失情况- 特征统计最常见的是
sum
,mean
,median
,var
,std
,max
,min
quantile
返回分位数值
# info()
train_data.info()
# describe()
train_data.describe()
# isna()
train_data.isna().sum()
# quantile
train_data["PClass"].quantile(0.5)
乘客ID 0
是否幸存 0
乘客登级(1/2/3等舱位) 0
乘客姓名 0
性别 0
年龄 177
堂兄弟/妹个数 0
父母与小孩个数 0
船票信息 0
票价 0
客舱 687
登船港口 2
dtype: int64
- Pandas中主要数据类型
Series
和DataFrame
- pandas 中具有两种基本的数据存储结构,存储一维
values
的Series
和存储二维values
的DataFrame
,在这两种结构上定义了很多的属性和方法。 Series
一般由四个部分组成,分别是序列的值data
、索引index
、存储类型dtype
、序列的名字name
。其中,索引也可以指定它的名字,默认为空。DataFrame
在Series
的基础上增加了列索引,一个数据框可以由二维的data
与行列索引来构造
- 数据集形状与唯一值
- 对
Series
使用unique
和nunique
可以分别得到其唯一值组成的列表和唯一值的个数,这种函数可以获得某列数据的种类情况 - 对
Series
使用value_counts()
可以得到唯一值和其对应出现的频数 - 使用
count()
与idxmax()
函数可以得到非缺失值个数、最大值对应的索引
# 统计唯一值与对应个数
train_data["Fare"].value_counts()
# 统计种类个数
train_data["Fare"].unique()
# 确定最大值索引
train_data["Fare"].idxmax()
- 索引与查找
- DataFrame的
columns
属性可以获得对应的列索引,可以根据此属性更改列名。 - 列索引最常见的形式为
[]
, 通过[列名]
可以从DataFrame
中取出相应的列,返回值为Series
,取出多的列可以通过["列名组成的列表"]
,返回值为DataFrame
。 - 基于
元素
的loc
索引器与基于位置
的iloc
索引器。loc
索引器的一般形式是loc[*, *]
,其中第一个*
代表行的选择,第二个*
代表列的选择,如果省略第二个位置写作loc[*]
,这个*
是指行的筛选。iloc
的使用与loc
完全类似,只不过是针对位置
进行筛选。
注意*
位置上共有5种合法对象,分别是:整数、整数列表、整数切片、布尔列表以及函数。函数的返回值必须是前面的四类合法对象中的一个,其输入同样也为 DataFrame
本身。
# 修改列名
dic = {"PassengerId":"乘客ID", "Survived":"是否幸存", "Pclass":"乘客登级(1/2/3等舱位)", "Name":"乘客姓名", "Sex": "性别", "Age": "年龄",
"SibSp": "堂兄弟/妹个数", "Parch":"父母与小孩个数", "Ticket":"船票信息", "Fare":"票价", "Cabin":"客舱", "Embarked": "登船港口"}
train_data.rename(columns=dic, inplace=True)
train_data.head()
train_data.columns
# train_data.columns = ["乘客ID", "是否幸存", "乘客等级(1/2/3等舱位)", "乘客姓名", "性别", "年龄", "堂兄弟/妹个数", "父母与小孩个数", "船票信息", "票价", "客舱", "登船港口"]
# 隐藏某几列数据
hideList = set(['PassengerId','Name','Age','Ticket'])
columnsList = set(test_data.columns)
tempColumnsList = list(columnsList - hideList)
print(tempColumnsList)
test_data[tempColumnsList]
# 查询第100、105、108行,Pclass、Name与Sex列
train_age_data.loc[[100, 105, 108], ["Pclass", "Name", "Sex"]]
train_age_data.iloc[[100, 105, 108], 2:5]
1.4 数据操作
知识点:
数据操作的重点在于索引对齐性
,pandas
的数据操作都是基于对齐行列索引后进行运算。
- 列的删除
drop()
删除函数,用于删除某列数据,inplace
参数可以确保能够操作到初始DataFrame
,columns
参数接收字符串列表或整数列表表示删除的列。
这里和del
命令区别在于内存索引是否回收。
# 删除多余列
test_data.drop(columns=["Unnamed: 0"], inplace=True)
test_data.head()
# del test_data["Unnamed: 0"]
- 筛选的逻辑
[]
索引接受布尔类型Series
,列表
为True
的位置所对应的行会被选中,False
则会被剔除
条件之间运算符不再是and
与or
,而是变为&
与|
,注意添加括号提高优先级.
# 索引对齐性
add_a_data = pd.DataFrame(np.arange(10, 40).reshape((10, 3)), columns=["columns_" + temp for temp in "abc"])
add_b_data = pd.DataFrame(np.random.randint(10, 50, 30).reshape((10, 3)), columns=["columns_" + temp for temp in "ace"])
add_a_data + add_b_data
#选择年龄小于10岁
train_data[train_data["年龄"] < 10]
# 选择年龄大于10岁小于50岁
train_data[(train_data["年龄"] > 10) & (train_data["年龄"]<50)]
- 排序sort_index()与sort_value()
- 排序共有两种方式,其一为
值排序
,其二为索引排序
sort_values()
参数by
接收列表表示要操作的列,ascending
参数表示是否降序排列sort_index()
索引排序的用法和值排序完全一致,只不过元素的值在索引
中,此时需要指定索引层的名字或者层号,用参数level
表示。另外,需要注意的是字符串的排列顺序由字母顺序
决定
# 根据票价和年龄降序排列
train_data.sort_values(by=["票价", "年龄"], ascending=False)
# 再更具舱位等级做升序排列
train_data.sort_values(by=["票价", "年龄"], ascending=False).sort_values("仓位等级", ascending=True)
1.5 总结
【总结】
本节中我们通过Pandas
的一些内置函数对数据进行了初步统计查看,了解自己在做什么数据分析,数据的大致情况是什么样子,我们为什么这么做数据分析,确定自己学习的意义。