Datawhale组队学习 2022年1月 动手学数据分析 第1章1
复习:这门课程得主要目的是通过真实的数据,以实战的方式了解数据分析的流程和熟悉数据分析python的基本操作。知道了课程的目的之后,我们接下来我们要正式的开始数据分析的实战教学,完成kaggle上泰坦尼克的任务,实战数据分析全流程。
这里有两份资料:
教材《Python for Data Analysis》和 baidu.com &
google.com(善用搜索引擎)
第一章:数据载入及初步观察
1.1 载入数据
数据集下载 https://www.kaggle.com/c/titanic/overview。
下载好以后把train.csv
文件复制几份,使用excel,分别把格式另存为成为tsv
、xlsx
,全都放到ipynb
文件所在文件夹下。
1.1.0 安装numpy和pandas
以管理员身份打开命令行,根据实际情况输入下面两条指令中的一条即可。
#没安装Anaconda就用pip,一般都没安装
pip install numpy pandas
#已经安装了Anaconda就用conda
conda install numpy pandas
有时候会出现网络问题,这时需要手动将pip或Anaconda的仓库地址修改到国内:Anaconda换源方法、pip换源方法,然后重新执行上面的指令。
1.1.1 任务一:导入numpy和pandas
以下代码运行环境均为jupyter notebook
。
import numpy as npy # 现实里没有npy,在这里弥补一下
import pandas as pd
import os #这个作用不大,只在查看当前路径时用到过一次
1.1.2 任务二:载入数据
【提示】相对路径载入报错时,尝试使用os.getcwd()查看当前工作目录。
- 使用相对路径载入数据
pd.read_csv("train.csv")
运行结果:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | S |
887 | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | C |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
- 使用绝对路径载入数据
pd.options.display.max_rows=2#让pandas每次只展示头尾共2行数据,看着更清爽一点
print(os.getcwd())
pd.read_csv("d:/myData/Datawhale/202201-DataAnalysis/第一单元项目集合/train.csv")
运行结果:
D:\myData\Datawhale\202201-DataAnalysis\第一单元项目集合
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
【思考】知道数据加载的方法后,试试pd.read_csv()和pd.read_table()的不同,如果想让他们效果一样,需要怎么做?了解一下'.tsv'和'.csv'的不同,如何加载这两个数据集?
下面尝试使用pd.read_csv
读取tsv文件:
pd.read_csv('train.tsv')
运行结果:
PassengerId\tSurvived\tPclass\tName\tSex\tAge\tSibSp\tParch\tTicket\tFare\tCabin\tEmbarked | |
---|---|
0 | 1\t0\t3\t"Braund\t Mr. Owen Harris"\tmale\t22... |
... | ... |
890 | 891\t0\t3\t"Dooley\t Mr. Patrick"\tmale\t32\t0... |
891 rows × 1 columns
尝试用pd.read_table
读取csv文件:
pd.read_table('train.csv')
运行结果:
PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked | |
---|---|
0 | 1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/... |
... | ... |
890 | 891,0,3,"Dooley, Mr. Patrick",male,32,0,0,3703... |
891 rows × 1 columns
由于文件中的分隔符与被调用方法的默认分隔符不同,文件被认为只有一个字段。
解决方法:通过sep
参数设置分隔符,这可以让pd.read_csv
和pd.read_table
表现一致。
pd.read_table('train.csv',sep=',')
运行结果:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
pd.read_csv('train.tsv',sep='\t')
运行结果:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund\t Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
890 | 891 | 0 | 3 | Dooley\t Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
如上面两段代码执行结果所示,指定sep
参数后,pandas能正确读取数据文件。
另外通过查阅资料发现,sep
参数还支持正则表达式,可以用来处理更复杂混乱的数据文件。
使用pd.read_excel
还可以读取Excel的xlsx
、xls
文件:
pd.read_excel('train.xlsx')
运行结果:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
【总结】加载的数据是所有工作的第一步,我们的工作会接触到不同的数据格式(eg:.csv
、.tsv
、.xlsx
),但是加载的方法和思路都是一样的,在以后工作和做项目的过程中,遇到之前没有碰到的问题,要多多查资料吗,使用google,了解业务逻辑,明白输入和输出是什么。
1.1.3 任务三:每1000行为一个数据模块,逐块读取
【思考】什么是逐块读取?为什么要逐块读取呢?
【提示】大家可以chunker(数据块)是什么类型?用for
循环打印出来出处具体的样子是什么?
如果指定了chunksize
参数,pd.read_csv
或pd.read_table
会返回一个迭代器,该迭代器迭代时,每次读取文件的最多chunksize
行(最后一次读取可能不够chunksize
行)。
每次读取到的部分以DataFrame
类型返回,遍历过程总共会返回\(\lceil \frac{n}{chunksize}\rceil\)个DataFrame
,其中n是数据的总行数。
逐块读取可以用来读取大文件,防止将文件一次性读入,因为内存占用过多产生各种问题。
chunker=pd.read_csv('train.csv',chunksize=1000)
ar=[]
for i in chunker:#遍历chunker
ar.append(i)#将每个小块放入数组ar中
ar[0]#查看第一个小块的内容
运行结果:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.25 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.75 | NaN | Q |
891 rows × 12 columns
1.1.4 任务四:将表头改成中文,索引改为乘客ID
【思考】所谓将表头改为中文其中一个思路是:将英文列名表头替换成中文。还有其他的方法吗?
对于某些英文资料,我们可以通过翻译来更直观的熟悉我们的数据,对于当前的泰坦尼克数据集:
PassengerId => 乘客ID
Survived => 是否幸存
Pclass => 乘客等级(1/2/3等舱位)
Name => 乘客姓名
Sex => 性别
Age => 年龄
SibSp => 堂兄弟/妹个数
Parch => 父母与小孩个数
Ticket => 船票信息
Fare => 票价
Cabin => 客舱
Embarked => 登船港口
这两个任务都有两种实现方式:
- 在读取是通过指定
read_csv
的参数来实现; - 读取完成后调用DataFrame对象提供的方法来实现。
读取时修改字段名:read_csv
函数的names
参数可以接受一个List类型的对象,List对象中的字符串数量必须和原始数据中的字段数量一致,最终返回的DataFrame对象字段名依次为List中的字符串。这个方法在原始数据字段名大部分需要更改时比较方便。
读取时指定索引:read_csv
函数的index_col
参数可以接受一个字符串或一个由字符串组成的List对象,表示要将索引设置为该参数指定的某列或某几列。
代码如下:
newNamesList=[
'乘客ID',
'是否幸存',
'乘客等级(1/2/3等舱位)',
'乘客姓名',
'性别',
'年龄',
'堂兄弟/妹个数',
'父母与小孩个数',
'船票信息',
'票价',
'客舱',
'登船港口',
]
pd.read_csv('train.csv',names=newNamesList,header=0,index_col='乘客ID')
运行结果:
是否幸存 | 乘客等级(1/2/3等舱位) | 乘客姓名 | 性别 | 年龄 | 堂兄弟/妹个数 | 父母与小孩个数 | 船票信息 | 票价 | 客舱 | 登船港口 | |
---|---|---|---|---|---|---|---|---|---|---|---|
乘客ID | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.25 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.75 | NaN | Q |
891 rows × 11 columns
读取完毕再修改DataFrame对象的字段名有两个途径:
- 使用DataFrame对象的
rename
方法,其中的columns
参数接受一个“可调用对象”,例如函数、字典等,该对象需要实现旧字段名到新字段名的映射,在原始数据字段名只有少部分需要修改时更方便。 - 直接修改DataFrame对象的
columns
属性,将其赋值为一个List,类似read_csv
函数的names
参数,用List对象中的字符串依次给各个字段重命名,List对象中的字符串数量必须和原始数据中的字段数量一致,在原始数据字段名大部分需要更改时比较方便。
想读取完毕再指定或修改DataFrame对象的索引,可以用set_index
方法,其中的keys
参数类似read_csv
函数的index_col
参数,可以接受一个字符串或一个由字符串组成的List对象,表示要将索引设置为某列或某几列。
代码演示如下:
newNamesDict={
'PassengerId':'乘客ID',
'Survived':'是否幸存',
'Pclass':'乘客等级(1/2/3等舱位)',
'Name':'乘客姓名',
'Sex':'性别',
'Age':'年龄',
'SibSp':'堂兄弟/妹个数',
'Parch':'父母与小孩个数',
'Ticket':'船票信息',
'Fare':'票价',
'Cabin':'客舱',
'Embarked':'登船港口',
}
df=pd.read_csv('train.csv')
df.rename(columns=a,inplace=True)#原地修改,不需要赋值回去
df=df.set_index(keys='乘客ID')#需要赋值回去
df
运行结果(下沉的字段表示当前索引):
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
乘客ID | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.25 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.75 | NaN | Q |
891 rows × 11 columns
1.2 初步观察
导入数据后,你可能要对数据的整体结构和样例进行概览,比如说,数据大小、有多少列,各列都是什么格式的,是否包含null等
1.2.1 任务一:查看数据的基本信息
df.info()
运行结果:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 1 to 891
Data columns (total 11 columns):
# | Column | Non-Null | Count | Dtype |
---|---|---|---|---|
0 | 是否幸存 | 891 | non-null | int64 |
1 | 乘客等级(1/2/3等舱位) | 891 | non-null | int64 |
2 | 乘客姓名 | 891 | non-null | object |
3 | 性别 | 891 | non-null | object |
4 | 年龄 | 714 | non-null | float64 |
6 | 父母与小孩个数 | 891 | non-null | int64 |
7 | 船票信息 | 891 | non-null | object |
8 | 票价 | 891 | non-null | float64 |
10 | 登船港口 | 889 | non-null | object |
dtypes: float64(2), int64(4), object(5)
memory usage: 83.5+ KB
1.2.2 任务二:观察表格前10行的数据和后15行的数据
前10行:
df.head(10)
运行结果:
是否幸存 | 乘客等级(1/2/3等舱位) | 乘客姓名 | 性别 | 年龄 | 堂兄弟/妹个数 | 父母与小孩个数 | 船票信息 | 票价 | 客舱 | 登船港口 | |
---|---|---|---|---|---|---|---|---|---|---|---|
乘客ID | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
10 | 1 | 2 | Nasser, Mrs. Nicholas (Adele Achem) | female | 14.0 | 1 | 0 | 237736 | 30.0708 | NaN | C |
10 rows × 11 columns
后15行:
df.tail(15)
运行结果:
是否幸存 | 乘客等级(1/2/3等舱位) | 乘客姓名 | 性别 | 年龄 | 堂兄弟/妹个数 | 父母与小孩个数 | 船票信息 | 票价 | 客舱 | 登船港口 | |
---|---|---|---|---|---|---|---|---|---|---|---|
乘客ID | |||||||||||
877 | 0 | 3 | Gustafsson, Mr. Alfred Ossian | male | 20.0 | 0 | 0 | 7534 | 9.8458 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
15 rows × 11 columns
1.2.4 任务三:判断数据是否为空,为空的地方返回True,其余地方返回False
df.isnull()
运行结果:
是否幸存 | 乘客等级(1/2/3等舱位) | 乘客姓名 | 性别 | 年龄 | 堂兄弟/妹个数 | 父母与小孩个数 | 船票信息 | 票价 | 客舱 | 登船港口 | |
---|---|---|---|---|---|---|---|---|---|---|---|
乘客ID | |||||||||||
1 | False | False | False | False | False | False | False | False | False | True | False |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
891 | False | False | False | False | False | False | False | False | False | True | False |
891 rows × 11 columns
如上所示,isnull()
函数会返回另一个DataFrame
对象,与原DataFrame
对象形状相同,内容为布尔值,表示df
中该位置是否为空。因为返回的是DataFrame
对象,我们就可以调用head()
方法查看前几行,也可以用sum()
方法求每个字段总共缺失多少数据。
pd.options.display.max_rows=15
df.isnull().sum()
运行结果:
是否幸存 0
乘客等级(1/2/3等舱位) 0
乘客姓名 0
性别 0
年龄 177
堂兄弟/妹个数 0
父母与小孩个数 0
船票信息 0
票价 0
客舱 687
登船港口 2
dtype: int64
【总结】上面的操作都是数据分析中对于数据本身的观察
【思考】对于一个数据,还可以从哪些方面来观察?找找答案,这个将对下面的数据分析有很大的帮助
1.3 保存数据
1.3.1 任务一:将你加载并做出改变的数据,在工作目录下保存为一个新文件train_chinese.csv
#写入代码
# 注意:不同的操作系统保存下来可能会有乱码。大家可以加入`encoding='GBK' 或者 ’encoding = ’utf-8‘‘`
df.to_csv('my_train_chinese.csv')
pd.read_csv('my_train_chinese.csv')
运行结果:
乘客ID | 是否幸存 | 乘客等级(1/2/3等舱位) | 乘客姓名 | 性别 | 年龄 | 堂兄弟/妹个数 | 父母与小孩个数 | 船票信息 | 票价 | 客舱 | 登船港口 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | S |
887 | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | C |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
保存到CSV文件再读取,字段名称已经修改,但索引信息丢失。
【总结】数据的加载以及入门,接下来就要接触数据本身的运算,我们将主要掌握numpy和pandas在工作和项目场景的运用。