数据分析(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: int641.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: int641.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: float64Pandas中的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 882.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 02.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