Pandas的基础学习及实践操作
前言
数据分析在各个领域都具有重要的意义,并且在 AI 学习中起着至关重要的作用,是实现 AI 技术有效应用和发展的基础。Pandas 是 Python 的核心数据分析支持库,它有着数据读取与写入、数据预处理、数据选择与过滤、数据整合等作用。
所以,掌握pandas的操作和使用对于学习数据分析、学习AI有很重要的作用。下面我就结合一个例子进行pandas的学习。
Part 1——数据载入及初步观察
我们以一个名为’train.csv‘的泰坦尼克的数据进行实践。
一、安装并导入库
- 首先需要安装
numpy
和pandas
两个库。
pip install numpy
pip install pandas
- 打开python后导入库
import pandas as pd
import numpy as np
二、载入数据
- 载入数据
在载入数据时可以选择相对路径或绝对路径载入数据。
#相对路径
df = pd.read_csv('./train.csv')
#绝对路径
df = pd.read_csv('E:\Python\workspace\pandas入门/train.csv')
- 由于python对于不同格式的文件,解析的方式也不同。所以当我们载入文件时,应该辨别文件类型,“对症下药”:
如:
'.tsv'
是用 ‘\t’ 作分隔符的文件,'.csv'
是用 ‘,’ 作分隔符的文件。
pd.read_csv()
用于读取以’,'作为分隔符的文本文件。pd.read_table()
用于读取以\t作为分隔符的文本文件。
所以读取文件时:
#对'.csv'文件
pd.read_csv('train.csv')
pd.read_table('train.csv',sep=',')
#对'.tsv'文件
pd.read_table('train.tsv')
pd.read_csv('train.tsv',sep='\t')
- 逐块读取
- 逐块读取是将数据分成小块,每次读取分析一小块的过程。
使用逐块读取可以避免因为数据过大造成的内存不足,读取分析过程可以先针对一块完成,再释放空间载入下一块;也可以提高数据分析效率,一块数据较小加载时间短,同时可以通过对于一块数据的分析处理了解数据的大致全貌。
数据逐块读取,我们可以用以下的代码:
chunker = pd.read_csv('./train.csv',chunksize=1000)
- 修改表头
在面对需要修改每列名的时候,我们有两种修改方法:
首先,可以在导入数据时就修改
#将原先的英文列名改为了中文列名
df = pd.read_csv('./train.csv',names=['乘客ID','是否幸存','仓位等级','姓名','性别','年龄','兄弟姐妹个数','父母子女个数','船票信息','票价','客舱','登船港口'],header=0)
或者,在导入后使用rename()
函数修改信息
df.rename(columns = {'PassengerId':'乘客ID'}, inplace = True)
三、初步观察
在初步观察阶段,我们可以总体观察数据的大致组成(如:数据由几行几列组成,其中列信息有哪几个,行信息代表什么;数据中有无空值等)接下来我就从这几个方面进行初步观察。
- 查看基本信息
df.info()
结果:
num | Column | Non-Null | Dtype |
---|---|---|---|
0 | 是否幸存 | 891 non-null | int64 |
1 | 仓位等级 | 891 non-null | int64 |
2 | 姓名 | 891 non-null | object |
3 | 性别 | 891 non-null | object |
4 | 年龄 | 714 non-null | float64 |
5 | 兄弟姐妹个数 | 891 non-null | int64 |
6 | 父母子女个数 | 891 non-null | int64 |
7 | 船票信息 | 891 non-null | object |
8 | 票价 | 891 non-null | float64 |
9 | 客舱 | 204 non-null | object |
10 | 登船港口 | 889 non-null | object |
dtypes: float64(2), int64(4), object(5) |
其中展现了列名、每列有几个非空数据、数据类型等。
- 观察数据前几行和后几行的数据
我们可以通过抽取数据的部分来体现全部数据。
如:
df.head() #抽取前几行数据
df.tail() #抽取后几行数据
- 判断数据是否为空
由前面对数据的观察发现数据中有空值,我们可以用以下函数判断数据是否为空
df.isnull().head(5) #判断前五行所有元素是否为空值
结果将会输出bool类型的结果,如下:
乘客ID | 是否幸存 | 仓位等级 | 姓名 | 性别 | 年龄 | 兄弟姐妹个数 | 父母子女个数 | 船票信息 | 票价 | 客舱 | 登船港口 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | False | False | False | False | False | False | False | False | False | True | False |
2 | False | False | False | False | False | False | False | False | False | Flase | False |
3 | False | False | False | False | False | False | False | False | False | True | False |
4 | False | False | False | False | False | False | False | False | False | Flase | False |
5 | False | False | False | False | False | False | False | False | False | True | False |
这种bool类型的数据可以当作数据分类的依据
四、保存数据
可以将你加载并做出改变的数据,在工作目录下保存为一个新文件
代码演示:
#该操作是把列名改为中文的文件保存为了train_chinese
df.to_csv('train_chinese.csv',encoding='GBK')
- 注意:不同的操作系统保存下来可能会有乱码。可以加入
encoding='GBK'
或者’encoding = ’utf-8‘‘
避免乱码出现。
Part2——Numpy、Pandas基础
为了实现后面的数据分析,我们接下来学习一些numpy和pandas的基础。其中pandas为数据分析的主力,numpy主要在数据计算、构造随机数组方面有作用。
一、Numpy基础
- 构造数组
在numpy中有多种可以构造的数组类型,接下来逐个介绍:
- 普通一维/多维数组:这样的数组可以手动输入各项数据来构造。
array1 = np.array([1,2,3,4,5]) #构造一维数组
array2 = np.array ([[1,2,3],[4,5,6],[7,8,9]]) #构造矩阵格式(多维数组)
以上array1将输出一个向量、array2将输出一个3*3的矩阵。
- 构造特殊数组:可以构造等差数组、随机数组、全一/全零数组、单位矩阵等特殊数组。
array1 =np.arange(0,100,10) #构造等差的数组(数据由0~100前闭后开,由10为间距)
random_array = np.random.rand(10) #生成随机数组(数据都为0~1)
array2 = np.linspace(0,10,50) #含头含尾等距分布,分为50份
array3 =np.zeros(3)
#生成 array([0., 0., 0.])
array4 =np.zeros((3,3))
'''生成 array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])'''
array5 = np.ones((3,3)) #全一矩阵
array6 = np.empty((5,5)) #全空矩阵
array7 = np.identity(3) #3*3的单位矩阵
- 数值计算
numpy中有多个函数可以用来数据计算,代码如下:
np.sum(array1) #array1求和
np.sum(array1,axis=0) #array1逐列求和
np.sum(array1,axis=1) #array1逐行求和
np.dot(x,y) #x、y两矩阵乘积
array1.min()
array1.argmin() #求最小值的索引位置
array1.mean() #平均值
array1.std() #标准差
array1.var() #方差
array1.round() #四舍五入
array1.round(decimals= 1) #指定精度
- 文件读写(不常用)
#文件读取(可指定分隔符、指定删去哪一行、使用哪几列)
data = np.loadtxt('kk3.txt',delimiter=",",skiprows=1,usecols = (0,1,3))
#文件写入
np.savetxt('kk4.txt',array1)
二、pandas基础
Pandas中一共有三种数据结构,分别为:Series
、DataFrame
和MultiIndex
。其中Series是一维数据结构,DataFrame是二维的表格型数据结构,MultiIndex是三维的数据结构。我们的重点为二维的DataFrame。 接下来是几种基本操作。
- 基本信息查看
使用pandas可以对数据进行多种基本信息的查看。
代码如下:
df.info() #全体信息查看(上面用过)
df.index #索引查看
'''输出结果:RangeIndex(start=0, stop=891, step=1) '''
df.columns #列名查看
df.describe() #得到基本统计特性
- 其中,
.describe()
可以得到数据的基本统计特性(特别好用),输出结果如下:
0 | PassengerID | Survived | Pclass | Age | SibSp | Parch | Fare |
---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 446.000000 | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 257.353842 | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 1.000000 | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 223.500000 | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 446.000000 | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 668.500000 | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 891.000000 | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
- 索引
除了python中一般的索引切片等基本操作还有以下操作:
- 在索引中中有两个重要的函数
.iloc()
,.loc()
,loc 用label来定位,iloc 用position来定位。
df.iloc[1] #括号中为索引
df.loc['b'] #括号中为标签
- 以bool类型作索引
df[df['Fare'] > 40]
df[df['Sex'] == 'male']
df.loc[df['Sex'] == 'male','Age'].mean()
(df['Age']>70).sum()
reset_index()
操作:它的作用是 重置索引。如果不用这个函数,可能会造成由于索引不符合原始值从而造成的数据分析的失误;可能会造成在两个DataFrame在合并时不匹配问题等。(drop等操作后面可能需要)
- 对象操作(增删改查)
- 增:增操作可以用
append()
、concat()
等函数。
#append()为某数组后增加另一数组,concat()为两数组合并
s1.append(s2,ignore_index=True)
df3 = pd.concat([df1,df2],axis=0)
df6 = pd.concat([df4,df5],axis=1)
- 删:删操作用到的是
del
和drop()
两个函数
del s1['a'] #单行删除
s1.drop(['b','d'],inplace = True) #多行删除
df5.drop(['j'],axis=0,inplace=True)
#drop中inplace=Flase可以当作隐藏数据来用(不改变原表格)
#使用drop后注意重置索引避免影响
- 改:改操作主要涉及到
.replace
和.rename
两个函数。其中,replace为改数据,rename为改行名/列名。
#对series
s1.replace(to_replace=100, value=101, inplace=False)#意思为:取代100这个数据,改为101,原数据不改
s1.rename(index = {'a':'A'},inplace = True)
#对dataframe
df.loc['a']['A'] = 150
df.rename(columns = {'a':'A','b':'B','c':'C'}, inplace = True)
- 查:查操作主要是靠指定索引来实现的。(基本操作如上“索引”内容)
df.iloc[1] #括号中为索引
df.loc['b'] #括号中为标签
- 数值运算
统计数据计算大部分和numpy相同。
df.mean() #平均值
df.median() #中位数
df.std() #标准差
df.var() #方差
df.cov() #相关差
df.corr() #相关系数
df['Age'].value_counts() #统计某一属性的个数
df['Age'].value_counts(ascending = True,bins = 5)#bins自动平均分组
- 其余重要函数
merge
合并函数
可以对left和right两个dataframe进行合并。
若两个数组有相同的一列,那一列可以当作key列。
left = pd.DataFrame({'key':['k0','k1','k2','k3'],
'A':['a0','a1','a2','a3'],
'B':['b0','b1','b2','b3']})
right = pd.DataFrame({'key':['k0','k1','k2','k3'],
'C':['c0','c1','c2','c3'],
'D':['d0','d1','d2','d3']})
pd.merge(left,right,on = 'key') #on = 通过什么指标进行合并
若on= 的列中有不同的元素,则可以选择生成交集或并集。
left = pd.DataFrame({'key1':['k0','k1','k2','k3'],
'key2':['k0','k1','k2','k3'],
'A':['a0','a1','a2','a3'],
'B':['b0','b1','b2','b3']})
right = pd.DataFrame({'key1':['k0','k1','k2','k3'],
'key2':['k0','k1','k2','k4'],
'C':['c0','c1','c2','c3'],
'D':['d0','d1','d2','d3']})
pd.merge(left,right,on = ['key1','key2']) #交集
pd.merge(left,right,on = ['key1','key2'],how='outer') #指定outer方法,变成并集
交集效果
0 | key1 | key2 | A | B | C | D |
---|---|---|---|---|---|---|
0 | k0 | k0 | a0 | b0 | c0 | d0 |
1 | k1 | k1 | a1 | b1 | c1 | d1 |
2 | k2 | k2 | a2 | b2 | c2 | d2 |
并集效果
0 | key1 | key2 | A | B | C | D |
---|---|---|---|---|---|---|
0 | k0 | k0 | a0 | b0 | c0 | d0 |
1 | k1 | k1 | a1 | b1 | c1 | d1 |
2 | k2 | k2 | a2 | b2 | c2 | d2 |
3 | k3 | k3 | a3 | b3 | NaN | NaN |
4 | k3 | k4 | NaN | NaN | c3 | d3 |
groupby
函数
该函数可以将相同数据部分合并,以便后续进行分析。
如:
df.groupby('Sex')['Age'].mean()
'''
代码意为:
求‘性别’栏为相同数据的‘年龄’的平均值
'''
'''
输出为
Sex
female 27.915709
male 30.726645
Name: Age, dtype: float64
'''
df.groupby('Sex')['Survived'].mean()
'''
代码意为:
求‘性别’栏为相同数据的‘存活率’的平均值
'''
'''
输出为
Sex
female 0.742038
male 0.188908
Name: Survived, dtype: float64
'''
Part3——数据分析实践
掌握了pandas的基本用法,我们继续把前面载入的泰坦尼克的数据进行分析实践。
- 泰坦尼克号数据(trian.csv)按票价和年龄两列进行综合排序(降序排列)
text = pd.read_csv('./train_chinese.csv',encoding='GBK')
text.sort_values(by=['票价','年龄'], ascending=False)
数据分析的重点在于分析二字。
在排序后,我们可以发现数据之间的关系从而得出结论或分析原因。如:根据票价和年龄的排序,我们可能可以分析到票价和年龄的关系;或通过票价的排序与其他数据的联系(如存活率),可以分析两者的关系等。
当你开始发现数据之间的关系了,数据分析就开始了。
- 通过泰坦尼克号数据如何计算出在船上最大的家族有多少人
根据题意‘求最大的家族’–>我们就可以分析家族和哪些指标有关,从而得出,‘兄弟姐妹个数’和‘父母子女个数’两个值与家族有关,由此分析我们就可以做出操作。
max(text['兄弟姐妹个数'] +text['父母子女个数'])
- 看看泰坦尼克号数据集中 票价、父母子女 这列数据的基本统计数据
'''
看看泰坦尼克号数据集中 票价 这列数据的基本统计数据
'''
text['票价'].describe()
得出:
count 891.000000
mean 32.204208
std 49.693429
min 0.000000
25% 7.910400
50% 14.454200
75% 31.000000
max 512.329200
Name: 票价, dtype: float64
从上面数据我们可以看出,一共有891个票价数据,平均值约为:32.20,标准差约为49.69,说明票价波动特别大,25%的人的票价是低于7.91的,50%的人的票价低于14.45,75%的人的票价低于31.00,票价最大值约为512.33,最小值为0。
'''
看看泰坦尼克号数据集中 父母子女个数 这列数据的基本统计数据
'''
text['父母子女个数'].describe()
得出:
count 891.000000
mean 0.381594
std 0.806057
min 0.000000
25% 0.000000
50% 0.000000
75% 0.000000
max 6.000000
Name: 父母子女个数, dtype: float64
从上面数据我们可以看出,一共有891个票价数据,均值为0.38,标准差为0.80,说明不同个体数据差别很大。且因为在数据中‘父母子女个数’在75%以下都为0,有可能可以说明该栏数据有数据收集不全的问题。我们则可以考虑到数据清洗或者数据筛选方面的操作。