数据分析(2) Pandas基本结构
Pandas主要有两种数据结构:Series和DataFrame。
(1)Series:类似于一维数组的对象,由数据(各种NumPy数据类型)以及与之相关标签(索引)组成。仅由一组数据也可产生简单的Series对象。注意:Series中的索引值是可以重复的。
(2)DataFrame:表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
引入方式:from pandas import Series, DataFrame 或 import pandas as pd
1 Series
1.1 创建方式
(1)通过列表创建:默认索引值,元组方式与列表相同
(2)通过数组创建:默认索引值,由于内置默认问题,数据类型与列表生成的会不一样
(3)通过字典创建:键值做索引
import pandas as pd import numpy as np list0 = [87, 90, 89] tuple0 = (87, 90, 89) dict0 = {‘语文‘: 87, ‘数学‘: 90, ‘英语‘: 89} ser1 = pd.Series(list0) ser2 = pd.Series(tuple0) ser3 = pd.Series(np.array(list0)) ser4 = pd.Series(dict0) print(‘===== 列表创建 =====\n‘, ser1) print(‘===== 元组创建 =====\n‘, ser2) print(‘===== 数组创建 =====\n‘, ser3) print(‘===== 字典创建 =====\n‘, ser4)# ===== 列表创建 ===== # 0 87 # 1 90 # 2 89 # dtype: int64 # ===== 元组创建 ===== # 0 87 # 1 90 # 2 89 # dtype: int64 # ===== 数组创建 ===== # 0 87 # 1 90 # 2 89 # dtype: int32 # ===== 字典创建 ===== # 语文 87 # 数学 90 # 英语 89 # dtype: int64
通过列表和数组创建的序列采用默认索引值,可通过index属性更改,如下例,ser1通过更改索引可变为与ser4相同的序列。
ser1.index = [‘语文‘, ‘数学‘, ‘英语‘] print(‘ser1更改索引后:\n‘, ser1)# ser1更改索引后: # 语文 87 # 数学 90 # 英语 89 # dtype: int64
也可创建时同步定义index属性,如下所示:ser1、ser4、ser5生成数组相同
ser5 = pd.Series(list0, index=[‘语文‘, ‘数学‘, ‘英语‘]) print(‘列表创建时指定索引值:\n‘, ser5)# 列表创建时指定索引值: # 语文 87 # 数学 90 # 英语 89 # dtype: int64
1.2 基本操作
1.2.1 赋值
Series对象本身以及索引都具有一个name属性,默认为空,根据需要可以进行赋值操作
scores = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65}) scores.name = ‘语文‘ scores.index.name = ‘考试成绩‘ print(scores)# 考试成绩 # Tom 89 # John 88 # Merry 96 # Max 65 # Name: 语文, dtype: int64
1.2.2 查询
Series获取多个值的方式类似NumPy中的ndarray的切片操作,主要有两种方式:
(1)[索引]:读取对应索引的数据,包含右侧索引
(2)[下标]:读取对应下标值的数据,不包括右侧下标
scores = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65}) print(‘===== 通过索引 =====\n‘, scores[‘Tom‘:‘Merry‘]) print(‘===== 通过下标 =====\n‘, scores[0:3])# ===== 通过索引 ===== # Tom 89 # John 88 # Merry 96 # dtype: int64 # ===== 通过下标 ===== # Tom 89 # John 88 # Merry 96 # dtype: int64
1.2.3 运算
Series保留了NumPy中的数组运算,并且进行数组运算的时候,索引与值之间的映射关系不会发生改变。
注意:在操作Series时,基本上可以把Series看成NumPy中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以应用到Series上。
当多个series对象之间进行运算的时候,如果不同series之间具有不同的索引值,那么运算会自动对齐相同索引值的数据,不同索引值赋值为NaN
s1 = pd.Series([12, 23, 45], index=[‘p1‘, ‘p2‘, ‘p3‘]) s2 = pd.Series([54, 43, 32, 21], index=[‘p2‘, ‘p3‘, ‘p4‘, ‘p5‘]) print(‘===== s1 + s2 =====\n‘, s1+s2)# ===== s1 + s2 ===== # p1 NaN # p2 77.0 # p3 88.0 # p4 NaN # p5 NaN # dtype: float64
1.2.4 缺失值操作
对于新建的index没有赋值时,Pandas会给定一个默认值NaN。
scores1 = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65}) new_index = [‘Tom‘, ‘Max‘, ‘Joe‘, ‘John‘, ‘Merry‘] scores2 = pd.Series(scores1, new_index) print(‘===== 原序列 =====\n‘, scores1) print(‘===== 更改索引后序列 =====\n‘, scores2)# ===== 原序列 ===== # Tom 89 # John 88 # Merry 96 # Max 65 # dtype: int64 # ===== 更改索引后序列 ===== # Tom 89.0 # Max 65.0 # Joe NaN # John 88.0 # Merry 96.0 # dtype: float64
Pandas中的isnull和notnull两个函数可以用于在Series中检测缺失值,这两个函数的返回时一个布尔类型的Series。
print(pd.isnull(scores2)) # Tom False # Max False # Joe True # John False # Merry False # dtype: bool print(scores2[pd.isnull]) # 过滤出缺失值项 # Joe NaN # dtype: float64
2 DataFrame
数据帧是二维数据结构,即数据以行列表格方式排列。
功能特点:潜在的列是不同数据类型;大小可变;标记轴(行和列)可以对行列执行算术运算。
2.1创建方式
pandas.DataFrame(data, index, columns, dtype, copy)
(1)通过二维数组创建:可在创建的时候命名index和columns
arr = np.array([ [‘Tom‘, 76], [‘Gerry‘, 98], [‘John‘, 85]]) df01 = pd.DataFrame(arr) df02 = pd.DataFrame(arr, index=[1, 2, 3], columns=[‘姓名‘, ‘成绩‘]) print(‘===== 数组直接创建 =====\n‘, df01) print(‘===== 重定义行列属性 =====\n‘, df02)# ===== 数组直接创建 ===== # 0 1 # 0 Tom 76 # 1 Gerry 98 # 2 John 85 # ===== 重定义行列属性 ===== # 姓名 成绩 # 1 Tom 76 # 2 Gerry 98 # 3 John 85
(2)通过字典方式创建:字典的value必须是长度相等的序列或一个标量,不可创建时命名index和columns,要通过更改自身index、colunms属性实现
dic = { # value必须是长度相等的序列或一个标量 ‘语文‘: [70, 80, 90], ‘数学‘: [80, 88, 90], ‘英语‘: [80, 78, 88] } df01 = pd.DataFrame(dic) print(‘===== 字典直接创建 =====\n‘, df01) # df02 = pd.DataFrame(dic, index=[‘one‘, ‘two‘, ‘three‘], columns=[‘a‘, ‘b‘, ‘c‘]) # 该方法等同于增加,不可行 df01.index = [‘one‘, ‘two‘, ‘three‘] # 通过改变自身属性 df01.columns = [[‘a‘, ‘b‘, ‘c‘]] print(‘===== 重定义行列属性 =====\n‘, df01)# ===== 字典直接创建 ===== # 语文 数学 英语 # 0 70 80 80 # 1 80 88 78 # 2 90 90 88 # ===== 重定义行列属性 ===== # a b c # one 70 80 80 # two 80 88 78 # three 90 90 88
2.2 数据获取
2.2.1 列数据
通过列索引, eg: df[column_name],若选择多列,column_name为列名组成的列表[]
df03 = pd.DataFrame(np.random.randint(1, 9, (3, 3)), index=list(‘ABC‘), columns=list(‘abc‘)) print(‘===== 数据结构 =====\n‘, df03) print(‘===== 列选择 =====\n‘, df03[[‘a‘, ‘b‘]]) df03[‘d‘] = [1, 2, 3] print(‘===== 列添加 =====\n‘, df03) # df03.pop(‘d‘) del df03[‘d‘] print(‘===== 列删除 =====\n‘, df03)# ===== 数据结构 ===== # a b c # A 5 6 2 # B 2 4 6 # C 6 3 7 # ===== 列选择 ===== # a b # A 5 6 # B 2 4 # C 6 3 # ===== 列添加 ===== # a b c d # A 5 6 2 1 # B 2 4 6 2 # C 6 3 7 3 # ===== 列删除 ===== # a b c # A 5 6 2 # B 2 4 6 # C 6 3 7
2.2.2 行数据
loc行名索引,iloc行的数字下标索引
print(‘===== loc 选择行 =====\n‘, df03.loc[‘A‘]) print(‘===== loc 选择某行某列 =====\n‘, df03.loc[‘A‘:‘B‘, ‘b‘:‘c‘]) print(‘===== iloc 选择行 =====\n‘, df03.iloc[1]) print(‘===== iloc 选择某行某列 =====\n‘, df03.iloc[1:3, 1:3])# ===== loc 选择行 ===== # a 2 # b 8 # c 4 # Name: A, dtype: int32 # ===== loc 选择某行某列 ===== # b c # A 8 4 # B 8 5 # ===== iloc 选择行 ===== # a 6 # b 8 # c 5 # Name: B, dtype: int32 # ===== iloc 选择某行某列 ===== # b c # B 8 5 # C 6 2
新增与修改行的方法可参照列操作,删除行要使用drop()方法,带返回值,axis为1表示删除列,0表示删除行。
df03 = df03.drop(‘C‘) print(‘===== 删除行 =====\n‘, df03)# ===== 删除行 ===== # a b c # A 4 8 4 # B 6 8 5
通过DataFrame的相关方式可以获取对应的列或者数据形成一个新的DataFrame, 方便后续进行统计计算。
缺省值:对于DataFrame/Series中的NaN一般采取的方式为删除对应的列/行或者填充一个默认值
2.2.3 缺省值处理
方法 | 说明 |
dropna | 根据标签的值中是否存在缺失数据对轴标签进行过滤(删除),可以通过阈值的调节对缺失值的容忍度 |
fillna | 用指定值或者插值的方式填充缺失数据,比如: ffill或者bfill |
isnull | 返回一个含有布尔值的对象,这些布尔值表示那些值是缺失值NA |
notnull | isnull的否定式 |
(1)删除 dropna
df = pd.DataFrame([ [‘Tom‘, np.nan, 456.67, ‘M‘], [‘Merry‘, 34, 456.67, np.nan], [‘Gerry‘, np.nan, np.nan, np.nan], [‘John‘, 23, np.nan, ‘M‘], [‘Joe‘, 18, 385.12, ‘F‘], [np.nan, np.nan, np.nan, np.nan]], columns=[‘name‘, ‘age‘, ‘salary‘, ‘gender‘]) df1 = df.dropna() # 默认删除包含nan的行 df2 = df.dropna(axis=1) # 删除包含nan的列 df3 = df.dropna(how=‘all‘) # 删除所有元素为nan的行或列 print(‘===== 原数据 =====\n‘, df) print(‘===== 删除包含nan的行 =====\n‘, df1) print(‘===== 删除包含nan的列 =====\n‘, df2) print(‘===== 删除所有元素为nan的行或列 =====\n‘, df3)# ===== 原数据 ===== # name age salary gender # 0 Tom NaN 456.67 M # 1 Merry 34.0 456.67 NaN # 2 Gerry NaN NaN NaN # 3 John 23.0 NaN M # 4 Joe 18.0 385.12 F # 5 NaN NaN NaN NaN # ===== 删除包含nan的行 ===== # name age salary gender # 4 Joe 18.0 385.12 F # ===== 删除包含nan的列 ===== # Empty DataFrame # Columns: [] # Index: [0, 1, 2, 3, 4, 5] # ===== 删除所有元素为nan的行或列 ===== # name age salary gender # 0 Tom NaN 456.67 M # 1 Merry 34.0 456.67 NaN # 2 Gerry NaN NaN NaN # 3 John 23.0 NaN M # 4 Joe 18.0 385.12 F
(2)填充
print(‘===== 用0填充数据中的nan =====\n‘, df.fillna(0)) print(‘===== 用0替换数据中的nan =====\n‘, df.replace({np.nan: 0}))# ===== 用0填充数据中的nan ===== # name age salary gender # 0 Tom 0.0 456.67 M # 1 Merry 34.0 456.67 0 # 2 Gerry 0.0 0.00 0 # 3 John 23.0 0.00 M # 4 Joe 18.0 385.12 F # 5 0 0.0 0.00 0 # ===== 用0替换数据中的nan ===== # name age salary gender # 0 Tom 0.0 456.67 M # 1 Merry 34.0 456.67 0 # 2 Gerry 0.0 0.00 0 # 3 John 23.0 0.00 M # 4 Joe 18.0 385.12 F # 5 0 0.0 0.00 0
2.2.4 排序
(1)按索引排序
sort_index 对行或列索引进行排序。ascending 参数用于控制升序或降序,默认为升序。
ser = pd.Series(np.arange(0, 4), index=[list(‘bcda‘)]) print(‘===== 原数据 =====\n‘, ser) print(‘===== 升序 =====\n‘, ser.sort_index()) print(‘===== 降序 =====\n‘, ser.sort_index(ascending=False))# ===== 原数据 ===== # b 0 # c 1 # d 2 # a 3 # dtype: int32 # ===== 升序 ===== # a 3 # b 0 # c 1 # d 2 # dtype: int32 # ===== 降序 ===== # d 2 # c 1 # b 0 # a 3 # dtype: int32
在 DataFrame 上,sort_index(axis=0, ascending=True) 方法多了一个轴向的选择参数
df = pd.DataFrame(np.random.randint(1, 9, (4, 4)), columns=list(‘bcad‘), index=list(‘BDAC‘)) print(‘===== 原数据 =====\n‘, df) print(‘===== 升序 =====\n‘, df.sort_index(axis=1)) print(‘===== 降序 =====\n‘, df.sort_index(axis=1, ascending=False))# ===== 原数据 ===== # b c a d # B 5 2 3 8 # D 7 3 6 1 # A 8 7 5 8 # C 6 5 4 2 # ===== 升序 ===== # a b c d # B 3 5 2 8 # D 6 7 3 1 # A 5 8 7 8 # C 4 6 5 2 # ===== 降序 ===== # d c b a # B 8 2 5 3 # D 1 3 7 6 # A 8 7 8 5 # C 2 5 6 4
(2)按值排序
作用:既可以根据列数据,也可根据行数据排序。
注意: 必须指定by参数,即必须指定哪几行或哪几列;无法根据index名和columns名排序(由.sort_index()执行)
对Series按值进行排序, 排序时,任何缺失值默认都会被放到Series的末尾
print(‘===== 通过值排序 =====\n‘, ser.sort_values()) print(‘===== 通过列值排序 =====\n‘, df.sort_values(by=[‘d‘, ‘b‘])) print(‘===== 通过行值排序 =====\n‘, df.sort_values(by=‘B‘, axis=1, ascending=False))# ===== 通过值排序 ===== # b 0 # c 1 # d 2 # a 3 # dtype: int32 # ===== 通过列值排序 ===== # b c a d # B 6 7 8 3 # C 3 5 8 4 # A 3 1 7 7 # D 4 7 7 8 # ===== 通过行值排序 ===== # a c b d # B 8 7 6 3 # D 7 7 4 8 # A 7 1 3 7 # C 8 5 3 4