[DataWhale动手学系列] 01动手学数据分析笔记
特别鸣谢:DataWhale开源组织发起组织的这次动手学数据分析项目。
Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。Datawhale用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。
🔗官方网站链接:https://datawhale.club/index.html
🔗DataWhale微信公众号:Datawhale
0. Pandas介绍
Pandas 是 Python 的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。Pandas 的目标是成为 Python 数据分析实践与实战的必备高级工具,其长远目标是成为最强大、最灵活、可以支持任何语言的开源数据分析工具。经过多年不懈的努力,Pandas 离这个目标已经越来越近了。
Pandas 适用于处理以下类型的数据:
- 与 SQL 或 Excel 表类似的,含异构列的表格数据;
- 有序和无序(非固定频率)的时间序列数据;
- 带行列标签的矩阵数据,包括同构或异构型数据;
- 任意其它形式的观测、统计数据集, 数据转入 Pandas 数据结构时不必事先标记
🔗Pandas中文网:https://www.pypandas.cn/
1. 加载数据
本次动手学数据分析使用的数据为Kaggle上的泰坦尼克项目(Titanic: Machine Learning from Disaster)
🖇️数据集下载链接:https://www.kaggle.com/c/titanic/data
Titanic: Machine Learning from Disaster
处理直接从网页下载数据外,可以直接使用命令行下载,更加快速直接;
🔸如何使用命令行下载数据:
🔹首先要安装Kaggle API,具体安装步骤请查看官方GtiHub: https://github.com/Kaggle/kaggle-api
🔹安装好后,直接在电脑终端运行:kaggle competitions download -c titanic
1.1 导入numpy和pandas
import numpy as np
import pandas as pd
1.2 IO工具
pandas的I/O API是一组read函数,比如pandas.read_csv()函数。这类函数可以返回pandas对象。相应的write函数是像DataFrame.to_csv()一样的对象方法。下面是一个方法列表,包含了这里面的所有readers函数和writer函数。
1.3 CSV与文本文件读取
读文本文件 (a.k.a. flat files)的主要方法 is read_csv().
- 使用相对路径载入数据
df = pd.read_csv('train.csv')
- 使用绝对路径载入数据
df = pd.read_csv('/mydrive/Colab_Notebooks/DataWhela/Data Analysis/hands-on-data-analysis/第一单元项目集合/train.csv')
- read_csv()与read_table()两个函数的区别
df = pd.read_table('train.csv')
df.head(3)
df = pd.read_csv('train.csv')
df.head(3)
通过上述结果可以看出,read_csv()返回的数据的格式与read_table()的数据格式不同;read_csv()返回的数据的格式为制表后的,而read_table()的数据只用逗号隔开。因此,查看两个函数定义代码:
read Csv make_parser_ function('read csv', sep=',')
read csv= Appender( read csv doc)(read csv read_table=make_parser_function( 'read table', sep='\t')
read table=Appender( read table doc)(read table)
根据定义代码可以看出,两个函数的本质区别在于分隔符sep不同,其他,除了方法名不一样,其他都相同。
# 与read_csv()输出相同格式的数据
df = pd.read_table('train.csv',sep=',')
df.head(3)
1.4 逐块读取
由于通常数据集的数据量都是巨大的,如果直接读取所有数据,不仅速度慢,还消耗计算机资源;为了高效快捷的读取数据,从而使用逐块读取。
# df = pd.read_csv('train.csv',chunksize=1000)
df = pd.read_table('train.csv',sep=',',chunksize=1000)
chunk = df.get_chunk() #获取一个数据块
print(chunk)
1.5 更换表头与索引
将表头改成中文,索引改为乘客ID
df = pd.read_csv('train.csv',names=['乘客ID','是否幸存','乘客等级','乘客姓名','性别','年龄','堂兄弟/妹个数','父母与小孩个数','船票信息','票价','客舱','登船港口'],index_col='乘客ID',header=0)
- 直接暴力修改
df = pd.read_csv('train.csv')
df.columns = ['乘客ID','是否幸存','乘客等级','乘客姓名','性别','年龄','堂兄弟/妹个数','父母与小孩个数','船票信息','票价','客舱','登船港口']
df.head()
- 通过rename方法,注意参数inplace=True的时候,才能真正的在原来的DataFrame上进行修改。
df = pd.read_csv('train.csv')
df.rename(columns={'PassengerId':'乘客ID','Survived':'是否幸存','Pclass':'乘客等级','Name':'乘客姓名','Sex':'性别','Age':'年龄','SibSp':'堂兄弟/妹个数','Parch':'父母与小孩个数','Ticket':'船票信息','Fare':'票价','Cabin':'客舱','Embarked':'登船港口'},inplace=True)
df.head()
- 索引修改,在rename方法,如果不写columns=xx就默认修改索引了。
df = pd.read_csv('train.csv')
df.rename({0:'PassengerId'})
- rename()函数适合于修改个别的索引或者列名,如果需要大部分的修改或者全部修改的话就使用set_index()函数比较方便。
df.set_index('PassengerId',inplace=True)
- 修改表头与索引
df = pd.read_csv('train.csv')
df.rename(columns={'PassengerId':'乘客ID','Survived':'是否幸存','Pclass':'乘客等级','Name':'乘客姓名','Sex':'性别','Age':'年龄','SibSp':'堂兄弟/妹个数','Parch':'父母与小孩个数','Ticket':'船票信息','Fare':'票价','Cabin':'客舱','Embarked':'登船港口'},inplace=True)
df.set_index('乘客ID',inplace=True)
df.head()
1.6 查看数据基础信息
# DataFrame的基础属性
# 行数 列数
df.shape
# 列数据类型
df.dtypes
# 数据维度
df.ndim
# 行索引
df.index
# 列索引
df.columns
# 对象值,二维ndarray数组
df.values
# DataFrame整体情况
# 显示前10行,默认是5行
df.head(10)
# 显示末尾几行,默认是5
df.tail()
# 相关系数,如行数,列数,列索引、列非空值个数,列类型,内存占用
df.info()
# 快速统计结果,计数、均值、标准差、最大值、四分数、最小值
df.describe()
2. 数据结构
2.1.1 Series
Series
是带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据。轴标签统称为索引。调用 pd.Series
函数即可创建 Series:
s = pd.Series(data, index=index)
上述代码中,data
支持以下数据类型:
- Python 字典
- 多维数组
- 标量值(如,5)
index
是轴标签列表。不同数据可分为以下几种情况:
多维数组
data
是多维数组时,index 长度必须与 data 长度一致。没有指定 index
参数时,创建数值型索引,即 [0, ..., len(data) - 1]
。
>> s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
>> s
a 0.469112
b -0.282863
c -1.509059
d -1.135632
e 1.212112
dtype: float64
字典
Series 可以用字典实例化:
>> d = {'b': 1, 'a': 0, 'c': 2}
>> pd.Series(d)
b 1
a 0
c 2
dtype: int64
标量值
data
是标量值时,必须提供索引。Series
按索引长度重复该标量值。
>> Series(8., index=['a', 'b', 'c'])
a 8.0
b 8.0
c 8.0
dtype: float6
2.1.2 Series 类似多维数组
Series
操作与 ndarray
类似,支持大多数 NumPy 函数,还支持索引切片。
>> s[0]
0.4691122999071863
>> s[:3]
a 0.469112
b -0.282863
c -1.509059
dtype: float64
>> In [15]: s[s > s.median()]
a 0.469112
e 1.212112
dtype: float64
s[[4, 3, 1]]
e 1.212112
d -1.135632
b -0.282863
dtype: float64
np.exp(s)
a 1.598575
b 0.753623
c 0.221118
d 0.321219
e 3.360575
dtype: float64
2.1.3 Series 类似字典
Series 类似固定大小的字典,可以用索引标签提取值或设置值:
>> s['a']
0.4691122999071863
s['e'] = 12.
>> s
a 0.469112
b -0.282863
c -1.509059
d -1.135632
e 12.000000
dtype: float64
>> 'e' in s
True
2.2 DataFrame
DataFrame 是由多种类型的列构成的二维标签数据结构,类似于 Excel 、SQL 表,或 Series 对象构成的字典。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame 支持多种类型的输入数据:
- 一维 ndarray、列表、字典、Series 字典
- 二维 numpy.ndarray
- 结构多维数组或记录多维数组
Series
DataFrame
除了数据,还可以有选择地传递 index(行标签)和 columns(列标签)参数。传递了索引或列,就可以确保生成的 DataFrame 里包含索引或列。Series 字典加上指定索引时,会丢弃与传递的索引不匹配的所有数据。
d = {'one': [1., 2., 3., 4.],'two': [4., 3., 2., 1.]}
pd.DataFrame(d)
d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']), 'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
pd.DataFrame(d)
2.2.1 提取、添加、删除列
DataFrame 就像带索引的 Series 字典,提取、设置、删除列的操作与字典类似
>> df['one']
a 1.0
b 2.0
c 3.0
d NaN
Name: one, dtype: float64
>> df['three'] = df['one'] * df['two']
>> df['flag'] = df['one'] > 2
>> df
one two three flag
a 1.0 1.0 1.0 False
b 2.0 2.0 4.0 False
c 3.0 3.0 9.0 True
d NaN 4.0 NaN False
删除(del、pop\drop)列的方式也与字典类似:
test_1 = pd.read_csv('test_1.csv')
del test_1['a']
test_1.pop('a')
test_1.drop(['a'],axis=1,inplace=True)
2.2.2 索引 / 选择
索引基础用法如下:
# 我们以"Age"为筛选条件,显示年龄在10岁以下的乘客信息。
df[df.Age<10].head(3)
# 以"Age"为条件,将年龄在10岁以上和50岁以下的乘客信息显示出来
df[(df.Age>10)&(df.Age<50)].head(3)
# 第100行的"Pclass"和"Sex"的数据显示出来
df.loc[[100],['Pclass','Sex']]
# 第100,105,108行的"Pclass","Name"和"Sex"的数据显示出来
df.loc[[100,105,108],['Pclass','Name','Sex']]
# 使用iloc方法将midage的数据中第100,105,108行的"Pclass","Name"和"Sex"的数据显示出来
df.iloc[[100,105,108],[2,3,4]]
3. 探索性数据分析
3.1数据排序
#自己构建一个都为数字的DataFrame数据
d = {'2': [1., 2., 3., 4.],'1': [4., 3., 2., 1.],'3': [5., 23., 28., 30.]}
frame = pd.DataFrame(d, index=['a', 'c', 'd', 'b'])
- 将构建的DataFrame中的数据根据某一列,升序排列
frame.sort_values(by='1',ascending=False)
- 1.让行索引升序排序
frame.sort_index()
- 让列索引升序排序
frame.sort_index(axis=1)
- 让列索引降序排序
frame.sort_index(axis=1,ascending=False)
- 让任选两列数据同时降序排序
frame.sort_values(by=['2','3'])
3,2 探索性分析
在大数据时代,混乱的、无结构的、多媒体的海量数据,通过各种渠道源源不断地积累和记载着人类活动的各种痕迹。探索性数据分析可以成为了一个有效的工具。
美国2014年出版的《数据科学实战》(Rachel Schutt, Cathy O’Neil著,冯凌秉、王群峰译)一书中,探索性数据分析被列为数据科学工作流程中的一个能影响多个环节的关键步骤。(见下图)
- 对泰坦尼克号数据(trian.csv)按票价和年龄两列进行综合排序(降序排列)
df.sort_values(by=['票价','年龄'],ascending=False).head(20)
- 利用Pandas进行算术计算,计算两个DataFrame数据相加结果
df = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.random.randn(7, 3), columns=['A', 'B', 'C'])
df + df2
- 学会使用Pandas describe()函数查看数据基本统计信息
df.describe()
- 分别看看泰坦尼克号数据集中 票价、父母子女 这列数据的基本统计数据
df = pd.read_csv('train_chinese.csv')
df['票价'].describe()