Pandas是一个开源的Python分析结构化数据的扩展程序库,基础是Numpy。可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据,灵活高效地处理各种数据集,广泛应用在各种数据分析领域。
import numpy as np
import pandas as pd
数据分析与可视化基础 (1) :NumPy数组库
数据分析与可视化基础 (2) :Pandas标签库
数据分析与可视化基础 (3) :Matplotlib绘图库
文章目录
1 Pandas对象基础
1.1 一维对象:Series
一维对象Series面向向量,其索引即为标签。可通过pd.Series()
创建Series对象
- 字典创建法:直接将Python字典转化为Series对象
dict_v = {'a': 0, 'b': 0.25, 'c': 0.5, 'd': 0.75, 'e': 1}
sr = pd.Series(dict_v)
print(sr)
- 数组创建法:传入指定的列表、数组或张量,设置函数的参数:值
values
、标签index
。其中标签可省略,默认为从0开始的编号。
v = [1.5, 3, 4.5, 6, 7.5]
k = ['a', 'b', 'c', 'd', 'e']
sr = pd.Series(v, index=k)
print(sr)
Series对象有两个属性:值values
、标签index
。
无论是用列表、NumPy数组还是PyTorch张量来创建对象,最终的值均为NumPy数组。因此调用values
即可将Pandas的Series对象退化为NumPy数组。
v = np.array([53, 64, 72, 82])
k = ['1 号', '2 号', '3 号', '4 号']
sr = pd.Series(v, index=k)
print(sr, '\n')
print(sr.values) # 查看values属性
print(sr.index) # 查看index属性
1.2 二维对象:DataFrame
二维对象DataFrame面向矩阵,其不仅有行标签 ,还有列标签。可通过pd.DataFrame()
创建DataFrame对象
- 字典创建法:基于多个Series对象,每一个Series就是一列数据。传入一个Python字典,其每个键值对为列标签与该列的Series对象。
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
i = ['1 号', '2 号', '3 号', '4 号']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df)
若sr1和sr2的
index
不完全一致,则二维对象会取两者的并集,因此该对象就会产生一定数量的缺失值(NaN
)
- 数组创建法:传入指定的列表、数组或张量,设置函数的参数:值
values
、行标签index
、列标签columns
。其中行、列标签可省略,默认为从0开始的编号。
v = np.array([[53, '女'], [64, '男'], [72, '男'], [82, '女']]) # 数字自动转为字符串
i = ['1 号', '2 号', '3 号', '4 号']
c = ['年龄', '性别']
df = pd.DataFrame(v, index=i, columns=c)
print(df)
DataFrame对象有三个属性:值values
、行标签index
、列标签columns
。
与一维的Series对象同理,调用values
属性即可将Pandas的DataFrame对象退化为NumPy数组。
v = np.array([[53, '女'], [64, '男'], [72, '男'], [82, '女']]) # 数字自动转为字符串
i = ['1 号', '2 号', '3 号', '4 号']
c = ['年龄', '性别']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
arr = df.values
print(arr)
print(df.index)
print(df.columns, '\n')
arr = arr[:, 0].astype(int) # 提取0号列,并转化为整数型数组
print(arr)
2 对象的索引
Pandas的索引机制与Python列表、NumPy数组基本一致,存在以下两种索引:
- 显式索引
.loc[]
:使用Pandas对象提供的标签索引,与其他索引的区别为访问切片时包含右端点 - 隐式索引
.iloc[]
:使用数组本身自带的从0开始的索引
与NumPy数组一样,切片仅是视图,若想创建新变量,使用.copy()
方法即可。
2.1 一维对象的索引
索引一维对象时,可以省略loc
和iloc
,这样形式上就与NumPy数组一致。
v = [53, 64, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')
print(sr.loc['3号'], '\n') # sr.iloc[2]
print(sr.loc[['1号', '3号']], '\n') # sr.iloc[[[0, 2]]
print(sr.loc['1号':'3号']) # sr.iloc[0:3]
2.2 二维对象的索引
在NumPy数组中,花式索引输出的是一个向量。但在Pandas二维对象中,考虑到其行列标签的信息不能丢失,输出的是矩阵。
i = ['1号', '2号', '3号', '4号']
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')
print(df.loc['1号', '年龄'], '\n') # df.iloc[0, 0]
print(df.loc[['1号', '3号'], ['性别', '年龄']], '\n') # df.iloc[[0, 2], [1, 0]]
print(df.loc['1号':'3号', '年龄'], '\n') # df.iloc[0:3, 0]
print(df.loc['3号', :], '\n') # 提取行;df.iloc[2, :];可省略冒号
print(df.loc[:, '年龄']) # 提取列;df.iloc[:, 0];可省略冒号与loc/iloc
3 对象的变形
3.1 转置:.T
调用T
获取转置后的对象,用于处理某些行是特征、列是个体的畸形原始数据。
v = [[53, 64, 72, 82], ['女', '男', '男', '女']]
i = ['年龄', '性别']
c = ['1号', '2号', '3号', '4号']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
df = df.T
print(df)
3.2 翻转
利用切片机制对对象进行左右翻转.iloc[:, ::-1]
与上下翻转.iloc[::-1, :]
i = ['1号', '2号', '3号', '4号']
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')
print(df.iloc[:, ::-1], '\n') # 左右翻转
print(df.iloc[::-1, :]) # 上下翻转
3.3 重塑
类似PyThon字典,可以直接利用[]
运算符,将Series并入DataFrame,或从DataFrame分离Series
i = ['1号', '2号', '3号', '4号']
v1 = [10, 20, 30, 40]
v2 = ['女', '男', '男', '女']
v3 = [1, 2, 3, 4]
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
sr3 = pd.Series(v3, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')
df['牌照'] = sr3 # 一维对象与二维对象的合并:把sr3并入,新建一列
print(df, '\n')
sr4 = df['年龄'] # 从中分离出sr4
print(sr4)
3.4 拼接:pd.concat()
函数pd.concat()
可以拼接两个对象,与np.concatenate()
函数语法相似。一维对象Series与二维对象DataFrame的合并无需使用该函数,实为3.3重塑中的合并操作。
Pandas放弃了Python集合与字典的索引唯一特性,因此合并后的索引可能重复。可通过对对象的index
或columns
属性调用.is_unique()
方法来检查是否有重复索引。
# 一维对象的合并
v1 = [10, 20, 30, 40]
v2 = [40, 50, 60]
k1 = ['1号', '2号', '3号', '4号']
k2 = ['4号', '5号', '6号']
sr1 = pd.Series(v1, index=k1)
sr2 = pd.Series(v2, index=k2)
print(sr1, '\n')
print(sr2, '\n')
print(pd.concat([sr1, sr2]))
合并二维对象时需设置axis
参数,默认为0,axis=x
意义与NumPy中同为沿轴x。
# 二维对象的合并
v1 = [[10, '女'], [20, '男'], [30, '男'], [40, '女']]
v2 = [[1, '是'], [2, '是'], [3, '是'], [4, '否']]
v3 = [[50, '男', 5, '是'], [60, '女', 6, '是']]
i1 = ['1 号', '2 号', '3 号', '4 号']
i2 = ['1 号', '2 号', '3 号', '4 号']
i3 = ['5 号', '6 号']
c1 = ['年龄', '性别']
c2 = ['牌照', '是否参保']
c3 = ['年龄', '性别', '牌照', '是否参保']
df1 = pd.DataFrame(v1, index=i1, columns=c1)
df2 = pd.DataFrame(v2, index=i2, columns=c2)
df3 = pd.DataFrame(v3, index=i3, columns=c3)
print(df1, '\n')
print(df2, '\n')
print(df3, '\n')
print(pd.concat([df1, df2], axis=1), '\n') # 合并列对象(添加列特征)
print(pd.concat([df1, df3])) # 合并行对象(添加行个体)
4 对象的运算
执行基本运算时也是按元素运算,且可以使用NumPy的各种函数。
4.1 对象与系数的运算
# 一维对象与系数的运算
sr = pd.Series([53, 64, 72], index=['1 号', '2 号', '3 号'])
print(sr, '\n')
print(sr + 10, '\n')
print(sr * 10, '\n')
print(sr ** 2)
# 二维对象与系数的运算
sr = pd.Series([53, 64, 72], index=['1 号', '2 号', '3 号'])
v = [[53, '女'], [64, '男'], [72, '男']]
df = pd.DataFrame(v, index=['1号', '2号', '3号'], columns=['年龄', '性别'])
print(df, '\n')
df['减法'] = df['年龄'] - 5
df['除法'] = df['年龄'] / 5
df['取余'] = df['年龄'] % 3
print(df)
4.2 对象与对象的运算
对象做运算,必须保证其都是数字型对象,两个对象之间的维度可以不同(会产生缺失值)。
# 一维对象之间的运算
v1 = [10, 20, 30, 40]
v2 = [1, 2, 3]
k1 = ['1号', '2号', '3号', '4号']
k2 = ['1号', '2号', '3号']
sr1 = pd.Series(v1, index=k1)
sr2 = pd.Series(v2, index=k2)
print(sr1, '\n')
print(sr2, '\n')
print(sr1 + sr2, '\n')
print(sr1 * sr2, '\n')
print(sr1 ** sr2)
# 二维对象之间的运算
v1 = [[10, '女'], [20, '男'], [30, '男'], [40, '女']]
v2 = [2, 8, 8, 5]
i1 = ['1号', '2号', '3号', '4号']
c1 = ['年龄', '性别']
i2 = ['1号', '2号', '3号', '6号']
c2 = ['成绩']
df1 = pd.DataFrame(v1, index=i1, columns=c1)
df2 = pd.DataFrame(v2, index=i2, columns=c2)
print(df1, '\n')
print(df2, '\n')
df1['减法'] = df1['年龄'] - df2['成绩']
df1['除法'] = df1['年龄'] / df2['成绩']
df1['取余'] = df1['年龄'] % df2['成绩']
print(df1)
使用np.abs()
、np.cos()
、np.exp()
、np.log()
等数学函数时,会保留索引。
Pandas中仍然存在布尔型对象,用法参考NumPy即可,此处不多赘述。
5 对象的缺失值
5.1 发现缺失值:.isnull()
使用.isnull()
方法发现缺失值NaN
,生成布尔型对象。方法.notnull()
效果与之相反,相当于在前面加非号~
。
# 发现一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')
print(sr.isnull())
# 发现二维对象的缺失值
v = [[None, 1], [64, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
print(df.isnull())
5.2 剔除缺失值:.dropna()
使用.dropna()
方法剔除缺失值,直接丢弃。
# 剔除一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')
print(sr.dropna())
二维对象中,要么单独剔除含有缺失值的行,要么剔除含有缺失值的列。默认剔除行,可设置参数axis='columns'
来剔除列(极少用)。也可设置参数how='all'
来只有当全部为缺失值时才剔除。
# 剔除二维对象的缺失值
v = [[None, 1], [None, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
print(df.dropna(), '\n')
print(df.dropna(axis='columns'), '\n')
print(df.dropna(how='all'))
5.3 填充缺失值:.fillna()
使用.fillna()
方法填充缺失值,通常选用常数(0、均值…)、前值(method='ffill'
)或后值(method='bfill'
)来填充。
# 填充一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')
print(sr.fillna(0), '\n')
print(sr.fillna(np.mean(sr)), '\n')
print(sr.fillna(method='ffill'), '\n')
print(sr.fillna(method='bfill'))
# 填充二维对象的缺失值
v = [[None, 1], [None, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
print(df.fillna(0), '\n')
print(df.fillna(np.mean(df)), '\n')
print(df.fillna(method='ffill'), '\n')
print(df.fillna(method='bfill'))
6 数据分析
6.1 读取csv文件:pd.read_csv()
使用函数pd.read_csv()
读取csv文件为DataFrame对象,参数index_col
表示从第几列开始读取,默认为0。
df = pd.read_csv('data.csv')
6.2 聚合方法
调用.head()
方法可仅输出前五行。除此之外NumPy中所有的聚合函数在Pandas中均有对象版的聚合方法,且均为忽略缺失值的安全版本。
df.head() # 仅输出前五行
df.max()
df.min()
df.mean()
df.std()
df.sum()
可使用.describe()
描述方法直接查看所有聚合函数的信息。其中min、25%、50%、75%、max为把数据从小到大排序后的五个分位点,显然50%分位点即为中位数。如下例所示
# 填充二维对象的缺失值
v = [[None, 1], [None, 2], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')
print(df.describe())
6.3 数据透视:.pivot_table()
使用.pivot_table()
方法可创建数据透视,用法如下:
# Output为考察的核心,研究其他特征Input_r、Input_c与之的关系
df.pivot_table(Output, index=Input_r, columns=Input_c)
另有两个用于分割的函数:pd.cut()
指定分割序列、pd.cut()
指定分割段数。详见以下示例
【例】以虚构的示例数据为例,以“是否生还”特征为考察的核心,研究其它特征与之的关系。
df = pd.read_csv('elimination.csv')
print(df, '\n')
# 一个特征
print(df.pivot_table('是否生还', index='性别'), '\n')
# 两个特征
print(df.pivot_table('是否生还', index='性别', columns='等级'), '\n')
# 三个特征,以18岁为分水岭分为两部分
age = pd.cut(df['年龄'], [0, 18, 120])
print(df.pivot_table('是否生还', index=['性别', age], columns='等级'), '\n')
# 四个特征,将费用自动分为两部分
fare = pd.qcut(df['费用'], 2)
print(df.pivot_table('是否生还', index=['等级', fare], columns=['性别', age]))