Pandas is a software library written for the Python programming language for data manipulation and analysis. In particular, it offers data structures and operations for manipulating numerical tables and time series.
Topic 1 Data Structure 1.1 Overview Pandas包含以下三个数据结构 :
系列(Series
)
数据帧(DataFrame
)
面板(Panel
)
这些数据结构构建在Numpy 数组之上,这意味着它们处理速度很快.
数据结构
维数
描述
Series
1
一维数组, 大小不
可变,由同种数据类型 元素组成.
DataFrame
2
二维数组, 大小可变
的表格结构, 它含有一组有序的列, 每列可以是不同的数据类型(整型、字符串、 布尔值等)
Panel
3
大小可变
的三维数组
可以简单理解为, 高维数据结构是低维数据结构的容器. 例如,DataFrame
是Series
的容器, Panel
是DataFrame
的容器.
1.2 Series Series是由相同数据类型 组成的一维数组. 有三个关键点:
同种类型数据构成 (同 numpy 的 ndarray)
大小不
可变
数据可变
1.3 DataFrame 数据帧 (DataFrame ) 是大小可变的数据结构, 每列可以是不同的数据类型 (整型、字符串、布尔值等). 有三个关键点:
姓名
年龄
性别
等级
Maxsu
25
男
4.45
Katie
34
女
2.78
Vina
46
女
3.9
Lia
女
女
4.6
上表表示某销售团队的绩效评级数据, 数据以行和列表示, 每列表示一个属性, 每行代表一个人. DataFrame 四列的数据类型分别为: 字符串, 整数, 字符串, 浮点型.
1.4 Panel 面板(Panel )可以由不同的数据类型构成的三维数据结构, Panel
是DataFrame
的容器.
Topic 2 Series 序列 (Series ) 是 pandas 中的一维数据结构,类似于 python 中的 list 和 Numpy 中的 ndarray
对象,在 Series
中包含的数据类型可以是整数,浮点数,字符串,python对象等.
2.1 Series Creation Series 的构造函数如下:
1 2 3 4 5 6 7 pandas.Series(data, index, dtype, copy)
[例 2.1] 创建一个空的 Series
1 2 3 4 import pandas as pds = pd.Series() print('空 Series:\n' ,s)
输出结果是:
1 2 空 Series: Series([], dtype: float64)
[例 2.2] 从 ndarray 创建一个 Series
1 2 3 4 5 6 import pandas as pdimport numpy as npa = np.array(['a' ,'b' ,'c' ,'d' ]) s = pd.Series(a) print(s)
输出结果是:
1 2 3 4 5 0 a 1 b 2 c 3 d dtype: object
注:
我们其实可以根据实际情况传入索引, 也就是左边那一列
[例 2.3]
1 2 3 4 5 6 import pandas as pdimport numpy as npa = np.array(['a' ,'b' ,'c' ,'d' ]) s = pd.Series(a,index=[100 ,101 ,102 ,103 ]) print(s)
输出结果是:
1 2 3 4 5 100 a 101 b 102 c 103 d dtype: object
[例 2.4] 从字典创建一个 Series
key
是 index
, value
是 Series
的值
1 2 3 4 5 import pandas as pda = {'a' :1 ,'b' :2 ,'c' :3 } s = pd.Series(a) print(s)
输出结果是:
1 2 3 4 a 1 b 2 c 3 dtype: int64
注:
我们也可以传入索引
[例 2.5]
索引顺序保持不变, 缺少的元素使用NaN(不是数字)填充.
1 2 3 4 5 import pandas as pda = {'a' :1 ,'b' :2 ,'c' :3 } s = pd.Series(a,index=['b' ,'c' ,'d' ,'e' ,'a' ]) print(s)
输出结果是:
1 2 3 4 5 6 b 2.0 c 3.0 d NaN e NaN a 1.0 dtype: float64
[例 2.6] 从标量创建一个 Series
如果数据是标量类型, 则必须提供索引 . 重复该值以匹配索引的长度.
1 2 3 4 import pandas as pds = pd.Series(5 , index=[0 ,1 ,2 ,3 ]) print(s)
输出结果是:
1 2 3 4 5 0 5 1 5 2 5 3 5 dtype: int64
2.2 Reading Series Series 中的数据可以使用类似于访问 ndarray
中的数据来访问.
[例 2.7] 检索第一个元素
1 2 3 4 import pandas as pds = pd.Series([1 ,2 ,3 ,4 ,5 ],index=['a' ,'b' ,'c' ,'d' ,'e' ]) print('获取第一个元素:\n' ,s[0 ])
输出结果是:
[例 2.8] 获取前三个元素
1 2 3 4 5 import pandas as pds = pd.Series([1 ,2 ,3 ,4 ,5 ],index=['a' ,'b' ,'c' ,'d' ,'e' ]) print('获取前三个元素:' ) print(s[:3 ])
输出结果是:
1 2 3 4 5 获取前三个元素: a 1 b 2 c 3 dtype: int64
我们也能通过 Series
的 index
来访问其数据.
[例 2.9] 使用 index 访问单个数据
1 2 3 4 import pandas as pds = pd.Series([1 ,2 ,3 ,4 ,5 ],index=['a' ,'b' ,'c' ,'d' ,'e' ]) print('访问索引为 d 的元素:\n' ,s['d' ])
输出结果是:
[例 2.10] 使用索引访问多个元素
1 2 3 4 5 import pandas as pds = pd.Series([1 ,2 ,3 ,4 ,5 ],index=['a' ,'b' ,'c' ,'d' ,'e' ]) print('使用索引访问多个元素:' ) print(s[['a' ,'c' ,'d' ]])
输出结果是:
1 2 3 4 5 使用索引访问多个元素: a 1 c 3 d 4 dtype: int64
2.3 Properties of Series
属性
说明
axes
返回 Series 的索引列表
dtype
返回 Series 的数据类型
empty
判断 Series 是否为空, 若为空, 返回 True
ndim
返回基础数据的维数
size
返回基础数据中的元素个数
values
将 Series 作为 ndarray
返回
head()
返回前 n 个元素
tail()
返回最后 n 个元素
2.3.1 Series.axes [例 2.11] 返回 Series 的索引列表
1 2 3 4 5 import pandas as pdimport numpy as nps = pd.Series(np.random.randn(4 )) print('数据的索引是:\n' ,s.axes)
输出结果是:
1 2 数据的索引是: [RangeIndex(start=0, stop=4, step=1)]
2.3.2 Series.empty [例 2.12] 查看 Series 是否为空
1 2 3 4 5 import pandas as pdimport numpy as nps = pd.Series(np.random.randn(4 )) print('数据为空?\n' ,s.empty)
输出结果是:
2.3.3 Series.ndim [例 2.13] 返回数据的维数
1 2 3 4 5 import pandas as pdimport numpy as nps = pd.Series(np.random.randn(4 )) print('数据的维数:\n' ,s.ndim)
输出结果是:
2.3.4 Series.size [例 2.14] 查看 Series 中的元素个数
1 2 3 4 5 import pandas as pdimport numpy as nps = pd.Series(np.random.randn(4 )) print('Series 包含的元素个数:\n' ,s.size)
输出结果是:
2.3.5 Series.values [例 2.15] 将 Series 作为 ndarray 返回
1 2 3 4 5 6 7 8 9 import pandas as pdimport numpy as nps = pd.Series(np.random.randn(4 )) print('我们的数据是:\n' ,s) print('\n' ) print('将数据转换成 ndarray.' ) a = s.values print('数据类型是:\n' ,type (a))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 我们的数据是: 0 0.139829 1 -0.858539 2 -0.060587 3 0.087893 dtype: float64 将数据转换成 ndarray. 数据类型是: <class 'numpy.ndarray'>
Topic 3 DataFrame DataFrame
是二维数据结构, 它包含一组有序的列, 每列可以是不同的数据类型, DataFrame
既有行索引, 也有列索引, 它可以看作是Series
组成的字典, 不过这些Series
共用一个索引. 其包含以下几个功能特点:
不同的列可以是不同的数据类型
大小可变
包含行索引和列索引
可以对行和列执行算术运算
3.1 DataFrame Creation DataFrame 的构造函数如下:
1 2 3 4 5 6 7 8 pandas.DataFrame(data, index, columns, dtype, copy)
[例 3.1] 创建一个空的 DataFrame
1 2 3 4 import pandas as pddf = pd.DataFrame() print(df)
输出结果是:
1 2 3 Empty DataFrame Columns: [] Index: []
[例 3.2] 从一个二维列表创建 DataFrame
1 2 3 4 5 import pandas as pdl = [['Alex' ,10 ],['Bob' ,12 ],['Clarke' ,13 ]] df = pd.DataFrame(l, columns=['Name' ,'Age' ]) print(df)
输出结果是:
1 2 3 4 Name Age 0 Alex 10 1 Bob 12 2 Clarke 13
[例 3.3] 从一个 dict 创建 DataFrame
1 2 3 4 5 import pandas as pddata = {'Name' :['Tom' ,'Jack' ,'Steve' ,'Ricky' ],'Age' :[28 ,34 ,29 ,42 ]} df = pd.DataFrame(data, index=['1st' ,'2nd' ,'3rd' ,'4th' ]) print(df)
输出结果是:
1 2 3 4 5 Name Age 1st Tom 28 2nd Jack 34 3rd Steve 29 4th Ricky 42
[例 3.4] 从 ndarray 创建 DataFrame
1 2 3 4 5 import pandas as pda = np.array([['Tom' ,28 ],['Jack' ,34 ],['Steve' ,29 ],['Ricky' ,42 ]]) df = pd.DataFrame(a, index=['1st' ,'2nd' ,'3rd' ,'4th' ],columns=['Name' ,'Age' ]) print(df)
输出结果是:
1 2 3 4 5 Name Age 1st Tom 28 2nd Jack 34 3rd Steve 29 4th Ricky 42
[例 3.5] 从 Series 字典来创建 DataFrame
1 2 3 4 5 6 7 import pandas as pdd = {'one' : pd.Series([1 , 2 , 3 ], index=['a' , 'b' , 'c' ]), 'two' : pd.Series([1 , 2 , 3 , 4 ], index=['a' , 'b' , 'c' , 'd' ])} df = pd.DataFrame(d) print(df)
输出结果是:
1 2 3 4 5 one two a 1.0 1 b 2.0 2 c 3.0 3 d NaN 4
3.2 DataFrame Operations 3.2.1 Reading Data from Columns 1 2 3 4 5 import pandas as pda = np.array([['Tom' ,28 ],['Jack' ,34 ],['Steve' ,29 ],['Ricky' ,42 ]]) df = pd.DataFrame(a, index=['1st' ,'2nd' ,'3rd' ,'4th' ],columns=['Name' ,'Age' ]) print(df['Name' ])
输出结果是:
1 2 3 4 5 1st Tom 2nd Jack 3rd Steve 4th Ricky Name: Name, dtype: object
3.2.2 Reading Data from Rows 有两种方式读取行数据:
添加列有两种方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import pandas as pda = np.array([['Tom' ,28 ],['Jack' ,34 ],['Steve' ,29 ],['Ricky' ,42 ]]) df = pd.DataFrame(a, index=['1st' ,'2nd' ,'3rd' ,'4th' ],columns=['Name' ,'Age' ]) print('原 DataFrame:' ) print(df) print('\n' ) print('通过传入一个新的 Series 来增加新列:' ) df['Sex' ] = pd.Series(['Male' ,'Male' ,'Male' ,'Female' ],index=['1st' ,'2nd' ,'3rd' ,'4th' ]) print(df) print('\n' ) print('通过操作已有列来增加新列:' ) df['Name and Sex' ] = df['Name' ] + df['Sex' ] print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 原 DataFrame: Name Age 1st Tom 28 2nd Jack 34 3rd Steve 29 4th Ricky 42 通过传入一个新的 Series 来增加新列: Name Age Sex 1st Tom 28 Male 2nd Jack 34 Male 3rd Steve 29 Male 4th Ricky 42 Female 通过操作已有列来增加新列: Name Age Sex Name and Sex 1st Tom 28 Male TomMale 2nd Jack 34 Male JackMale 3rd Steve 29 Male SteveMale 4th Ricky 42 Female RickyFemale
删除列有两种方式:
使用 del
关键字
使用 DataFrame.pop()
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import pandas as pda = np.array([['Tom' ,28 ],['Jack' ,34 ],['Steve' ,29 ],['Ricky' ,42 ]]) df = pd.DataFrame(a, index=['1st' ,'2nd' ,'3rd' ,'4th' ],columns=['Name' ,'Age' ]) df['Sex' ] = pd.Series(['Male' ,'Male' ,'Male' ,'Female' ],index=['1st' ,'2nd' ,'3rd' ,'4th' ]) print('原 DataFrame:' ) print(df) print('\n' ) print('使用 del 关键字:' ) del df['Sex' ]print(df) print('\n' ) print('使用 DataFrame.pop() 函数' ) print('返回列:' ) df.pop('Age' ) print() print('修改之后的 DataFrame:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 原 DataFrame: Name Age Sex 1st Tom 28 Male 2nd Jack 34 Male 3rd Steve 29 Male 4th Ricky 42 Female 使用 del 关键字: Name Age 1st Tom 28 2nd Jack 34 3rd Steve 29 4th Ricky 42 使用 DataFrame.pop() 函数 返回列: 1st 28 2nd 34 3rd 29 4th 42 Name: Age, dtype: object 修改之后的 DataFrame: Name 1st Tom 2nd Jack 3rd Steve 4th Ricky
3.2.4 Adding and Deleting Rows 添加行只有一种方式: DataFrame.append(pandas.DataFrame)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as npdf1 = pd.DataFrame([[1 ,2 ],[3 ,4 ]],columns=['a' ,'b' ]) df2 = pd.DataFrame([[5 ,6 ],[7 ,8 ]],columns=['a' ,'b' ]) print('df1:' ) print(df1) print('\n' ) print('df2:' ) print(df2) print('\n' ) print('将 df2 添加到 df1 之后:' ) print(df1.append(df2))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 df1: a b 0 1 2 1 3 4 df2: a b 0 5 6 1 7 8 将 df2 添加到 df1 之后: a b 0 1 2 1 3 4 0 5 6 1 7 8
使用索引标签从 DataFrame 中删除行. 如果标签重复, 则会删除多行.
1 2 3 4 5 6 7 8 9 import pandas as npdf1 = pd.DataFrame([[1 ,2 ],[3 ,4 ]],columns=['a' ,'b' ]) df2 = pd.DataFrame([[5 ,6 ],[7 ,8 ]],columns=['a' ,'b' ]) df1 = df1.append(df2) print('删除行标为 0 的行:' ) df1 = df1.drop(0 ) print(df1)
输出结果是:
1 2 3 4 删除行标为 0 的行: a b 1 3 4 1 7 8
3.2.5 Reindexing and Renaming
DataFrame.reindex()
我们首先看对 Series 重新索引
1 2 3 4 5 6 7 8 9 10 import pandas as pd s = pd.Series([1 ,7 ,3 ,9 ],index=['d' ,'c' ,'a' ,'f' ]) print('我们的数据是:' ) print(s) print('\n' ) print('reindex 函数会对数据重新排序, 缺失值会有 NaN 填补:' ) s = s.reindex(index=['a' ,'b' ,'c' ,'d' ,'e' ,'f' ]) print(s)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 我们的数据是: d 1 c 7 a 3 f 9 dtype: int64 reindex 函数会对数据重新排序, 缺失值会有 NaN 填补: a 3.0 b NaN c 7.0 d 1.0 e NaN f 9.0 dtype: float64
和 fillna()
函数一样, reindex 可以选择重新索引时的数据插入方式来填补缺失值
1 2 3 4 5 6 7 8 9 10 import pandas as pds = pd.Series(['blue' ,'red' ,'black' ],index=[0 ,2 ,4 ]) print('我们的数据是:' ) print(s) print('\n' ) print('reindex 之后数据是:' ) s = s.reindex(index=range (6 ),method='ffill' ) print(s)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 我们的数据是: 0 blue 2 red 4 black dtype: object reindex 之后数据是: 0 blue 1 blue 2 red 3 red 4 black 5 black dtype: object
我们再来看一下对 DataFrame 的索引
1 2 3 4 5 6 7 8 9 10 11 import pandas as pdimport pandas as nps = pd.DataFrame(np.arange(9 ).reshape(3 ,3 ), index=['a' ,'c' ,'d' ], columns=['one' ,'two' ,'four' ]) print('我们的数据是:' ) print(s) print('\n' ) print('使用 reindex 填充数据, 传入参数 fill_value 可以填充缺失值:' ) s = s.reindex(index=['a' ,'b' ,'c' ,'d' ],columns=['one' ,'two' ,'three' ,'four' ],fill_value=100 ) print(s)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 我们的数据是: one two four a 0 1 2 c 3 4 5 d 6 7 8 使用 reindex 填充数据, 传入参数 fill_value 可以填充缺失值: one two three four a 0 1 100 2 b 100 100 100 100 c 3 4 100 5 d 6 7 100 8
DataFrame.rename()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import pandas as pdimport numpy as npdf = pd.DataFrame({"A" : [1 , 2 , 3 ], "B" : [4 , 5 , 6 ]}) df.rename(columns={"A" : "a" , "B" : "c" }) a c 0 1 4 1 2 5 2 3 6 df.rename(index={0 : "x" , 1 : "y" , 2 : "z" }) A B x 1 4 y 2 5 z 3 6 df.rename(str .lower, axis='columns' ) a b 0 1 4 1 2 5 2 3 6 df.rename({1 : 2 , 2 : 4 }, axis='index' ) A B 0 1 4 2 2 5 4 3 6
3.3 Properties of DataFrame
属性
描述
T
转置行和列
axes
返回 DataFrame 的行和列标签
dtype
返回 DataFrame 中每一列的数据类型
empty
若 DataFrame 为空, 则返回 True
ndim
返回 DataFrame 维度的数量, 默认为 2
shape
返回 DataFrame 的维度
size
返回 DataFrame 中元素的个数
values
将 DataFrame 中的数据以 ndarray
返回
head()
返回开头前 n
行
tail()
返回最后 n
行
3.3.1 DataFrame.T 返回DataFrame
的转置, 行和列将交换:
1 2 3 4 5 6 7 8 9 10 11 12 13 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ])} df = pd.DataFrame(d) print('原数据是:' ) print(df) print('\n' ) print('转置之后的数据是:' ) print(df.T)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 原数据是: Name Age Rating 0 Tom 25 4.23 1 James 26 3.24 2 Ricky 25 3.98 3 Vin 23 2.56 4 Steve 30 3.20 5 Minsu 29 4.60 6 Jack 23 3.80 转置之后的数据是: 0 1 2 3 4 5 6 Name Tom James Ricky Vin Steve Minsu Jack Age 25 26 25 23 30 29 23 Rating 4.23 3.24 3.98 2.56 3.2 4.6 3.8
3.3.2 DataFrame.axes 返回 DataFrame
的行轴标签和列轴标签列表
1 2 3 4 5 6 7 8 9 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ])} df = pd.DataFrame(d) print('行标签和列标签是:' ) print(df.axes)
输出结果是:
1 2 行标签和列标签是: [RangeIndex(start=0, stop=7, step=1), Index(['Name', 'Age', 'Rating'], dtype='object')]
3.3.3 DataFrame.dtypes 返回每列的数据类型
1 2 3 4 5 6 7 8 9 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ])} df = pd.DataFrame(d) print('每列的数据类型:' ) print(df.dtypes)
数据类型是:
1 2 3 4 5 每列的数据类型: Name object Age int64 Rating float64 dtype: object
3.4 DataFrame MultiIndex MultiIndex
表示多级索引, 它是从Index继承过来的, 其中多级标签用元组对象 来表示.
3.4.1 MultiIndex Creation 我们主要使用 pandas.MultiIndex.from_arrays()
来创建多级索引.
1 2 3 4 5 6 7 8 9 import pandas as pdimport numpy as npclass1=["A" ,"A" ,"B" ,"B" ,'B' ] class2=["x1" ,"x2" ,"y1" ,"y2" ,'y3' ] multi_index=pd.MultiIndex.from_arrays([class1,class2],names=["class1" ,"class2" ]) df = pd.DataFrame(np.random.randint(1 ,10 ,(5 ,3 )),index=multi_index) df
输出结果是:
Series和DataFrame的列名称属性就是columns, 他也可以是一个 MultiIndex
对象:
1 2 3 4 5 6 7 8 9 10 import numpy as npimport pandas as pdarrays = [['bar' , 'bar' , 'baz' , 'baz' , 'foo' , 'foo' , 'qux' , 'qux' ], ['one' , 'two' , 'one' , 'two' , 'one' , 'two' , 'one' , 'two' ]] multi_index = pd.MultiIndex.from_arrays(arrays,names=['FirstLevel' ,'SecondLevel' ]) df = pd.DataFrame(np.random.randn(3 , 8 ), index=['A' , 'B' , 'C' ], columns=multi_index) df
输出结果是:
3.4.2 Use of MultiIndex 我们再来看一下如何使用 MultiIndex 选择数据
首先, 获取FirstLevel是bar的所有数据:
输出结果是:
获取FirstLevel是bar, SecondLevel是one的所有数据:
输出结果是:
如果要选择第二层的列名为one的所有数据, 我们需要借助xs方法:
1 df.xs('one' ,level=1 ,axis=1 )
输出结果是:
或者使用名称代替数字:
1 df.xs('one' , level='SecondLevel' , axis='columns' )
输出结果是:
xs
不仅可以用来选择列, 也可以用来选择行:
1 2 3 4 5 6 7 8 9 10 11 12 13 import numpy as npimport pandas as pdclass1=["A" ,"A" ,"B" ,"B" ,'B' ] class2=["x1" ,"x2" ,"y1" ,"y2" ,'y3' ] multi_index=pd.MultiIndex.from_arrays([class1,class2],names=["class1" ,"class2" ]) df = pd.DataFrame(np.random.randint(1 ,10 ,(5 ,3 )),index=multi_index) print('我们的数据是:' ) print(df) print("\n" ) print('选取结果是:' ) df.xs('x1' ,level=1 ,axis='index' )
输出结果是:
注: 当然, 也可以使用我们学过的 loc
或者 iloc
函数.
3.5 DataFrame Iteration 我们可以直接迭代 DataFrame
和 Series
:
Series - 值
DataFrame - 列标签
看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as pdimport numpy as npN=20 df = pd.DataFrame({ 'A' : pd.date_range(start='2016-01-01' ,periods=N,freq='D' ), 'x' : np.linspace(0 ,stop=N-1 ,num=N), 'y' : np.random.rand(N), 'C' : np.random.choice(['Low' ,'Medium' ,'High' ],N).tolist(), 'D' : np.random.normal(100 , 10 , size=(N)).tolist() }) for col in df: print(col)
输出结果是:
若我们要遍历 DataFrame 中的行, 我们使用以下函数:
iteritems()
- 遍历每一列
iterrows()
- 遍历每一行
itertuples()
3.5.1 DataFrame.iteritems() 列为 key, 列中的值为 value.
1 2 3 4 5 6 7 8 import pandas as pdimport numpy as npdf = pd.DataFrame(np.random.randn(4 ,3 ), columns=['A' ,'B' ,'C' ]) for k,v in df.iteritems(): print('列名:' ,k) print(v) print('\n' )
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 列名: A 0 0.296866 1 -0.148633 2 1.621515 3 -0.660666 Name: A, dtype: float64 列名: B 0 -0.253393 1 0.574725 2 0.503636 3 0.204850 Name: B, dtype: float64 列名: C 0 1.317005 1 0.346061 2 0.358695 3 0.341376 Name: C, dtype: float64
3.5.2 DataFrame.iterrows() 返回迭代器,产生每个索引值以及包含每行数据的序列.
1 2 3 4 5 6 7 8 import numpy as npimport pandas as pddf = pd.DataFrame(np.random.randn(4 ,3 ), columns=['A' ,'B' ,'C' ]) for row_index, row in df.iterrows(): print('行 index 是:' , row_index) print(row) print('\n' )
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [102] df = pd.DataFrame(np.random.randn(4,3), columns=['A','B','C']) for row_index, row in df.iterrows(): print('行 index 是:', row_index) print(row) print('\n') 行 index 是: 0 A -0.831008 B -0.864205 C 0.146520 Name: 0, dtype: float64 行 index 是: 1 A -0.991669 B -2.374277 C -0.356669 Name: 1, dtype: float64 行 index 是: 2 A 2.209128 B -0.420584 C 0.506585 Name: 2, dtype: float64 行 index 是: 3 A -1.058109 B -0.000286 C 1.033392 Name: 3, dtype: float64
3.5.3 DataFrame.itertuples() itertuples()
方法将为DataFrame
中的每一行返回一个产生一个命名元组的迭代器. 元组的第一个元素将是行的相应索引值, 而剩余的值是行值.
1 2 3 4 5 6 7 8 9 10 import numpy as npimport pandas as pddf = pd.DataFrame(np.random.randn(4 ,3 ), columns=['A' ,'B' ,'C' ]) for row in df.itertuples(): print(row) print('行 index 是:' , row[0 ]) print('行的值是:' ) print(row[1 :]) print('\n' )
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Pandas(Index=0, A=-0.3540071641471044, B=1.6031505884204515, C=-0.4870924983750079) 行 index 是: 0 行的值是: (-0.3540071641471044, 1.6031505884204515, -0.4870924983750079) Pandas(Index=1, A=0.5879313227987284, B=-0.5026893763858423, C=0.6591968909105315) 行 index 是: 1 行的值是: (0.5879313227987284, -0.5026893763858423, 0.6591968909105315) Pandas(Index=2, A=-1.8100048151441157, B=0.7800415414210258, C=-0.47082706870345153) 行 index 是: 2 行的值是: (-1.8100048151441157, 0.7800415414210258, -0.47082706870345153) Pandas(Index=3, A=0.22830697450955625, B=-0.6997787075277464, C=1.6736471725117756) 行 index 是: 3 行的值是: (0.22830697450955625, -0.6997787075277464, 1.6736471725117756)
3.6 Sorting DataFrame Pandas 有两种排序方式, 它们分别是:
按 index (可以是行, 也可以是列)
按 values
我们先创建一个 DataFrame 用于之后的示例.
1 2 3 4 5 6 import pandas as pdimport numpy as npdf = pd.DataFrame(np.random.randn(10 ,2 ),index=[1 ,4 ,6 ,2 ,3 ,5 ,9 ,8 ,0 ,7 ],columns=['col2' ,'col1' ]) print('我们的数据是:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 我们的数据是: col2 col1 1 -0.270190 0.970122 4 -0.387794 0.023349 6 -0.340047 0.412159 2 0.473514 0.697203 3 -1.062665 0.666765 5 -0.157076 0.810648 9 0.601996 0.700997 8 1.305286 0.591112 0 0.272618 -0.105529 7 -2.122524 -0.613860
3.6.1 DataFrame.sort_index() 使用sort_index()
方法, 通过传递axis
参数和排序顺序, 可以对DataFrame
进行排序. 默认情况下, 按照升序对行 index 进行排序.
1 2 3 4 5 6 7 8 9 10 11 12 import pandas as pdimport numpy as npdf = pd.DataFrame(np.random.randn(10 ,2 ),index=[1 ,4 ,6 ,2 ,3 ,5 ,9 ,8 ,0 ,7 ],columns=['col2' ,'col1' ]) asc_sorted_df = df.sort_index(axis=0 ) desc_sorted_df = df.sort_index(axis=0 , ascending=False ) print('升序排序:' ) print(asc_sorted_df) print('\n' ) print('降序排序:' ) print(desc_sorted_df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 升序排序: col2 col1 0 0.509889 -0.863155 1 0.717766 -0.865105 2 -1.465073 0.501439 3 -0.891743 -0.772799 4 -1.086885 0.241132 5 0.104040 1.564791 6 -1.271712 0.074772 7 0.772256 -0.880302 8 -0.361009 -0.391085 9 0.255575 0.506795 降序排序: col2 col1 9 0.255575 0.506795 8 -0.361009 -0.391085 7 0.772256 -0.880302 6 -1.271712 0.074772 5 0.104040 1.564791 4 -1.086885 0.241132 3 -0.891743 -0.772799 2 -1.465073 0.501439 1 0.717766 -0.865105 0 0.509889 -0.863155
我们再看一下按列排序的情况
1 2 3 4 5 6 7 8 9 10 11 12 import pandas as pdimport numpy as npdf = pd.DataFrame(np.random.randn(10 ,2 ),index=[1 ,4 ,6 ,2 ,3 ,5 ,9 ,8 ,0 ,7 ],columns=['col2' ,'col1' ]) asc_sorted_df = df.sort_index(axis=1 ) desc_sorted_df = df.sort_index(axis=1 , ascending=False ) print('升序排序:' ) print(asc_sorted_df) print('\n' ) print('降序排序:' ) print(desc_sorted_df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 升序排序: col1 col2 1 -0.482662 1.857978 4 1.008759 0.157484 6 0.404661 0.084503 2 -0.350703 0.340782 3 -0.577663 -0.453446 5 0.136501 -1.253516 9 0.893234 -0.239606 8 1.246226 -0.945827 0 0.322587 -2.122998 7 -2.055323 0.208008 降序排序: col2 col1 1 1.857978 -0.482662 4 0.157484 1.008759 6 0.084503 0.404661 2 0.340782 -0.350703 3 -0.453446 -0.577663 5 -1.253516 0.136501 9 -0.239606 0.893234 8 -0.945827 1.246226 0 -2.122998 0.322587 7 0.208008 -2.055323
3.6.2 DataFrame.sort_values() sort_values()
是按值排序的方法. 它接受一个by
参数, 它将使用要与其排序值的DataFrame
的列名称.
1 2 3 4 5 6 7 8 import pandas as pdimport numpy as npdf = pd.DataFrame(np.random.randn(10 ,2 ),index=[1 ,4 ,6 ,2 ,3 ,5 ,9 ,8 ,0 ,7 ],columns=['col2' ,'col1' ]) sorted_df = df.sort_index(axis=1 ).sort_values(by=['col1' ,'col2' ],kind='mergesort' ,ascending=False ) print('排序结果是:' ) print(sorted_df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 排序结果是: col1 col2 2 1.643330 0.634745 7 1.424638 -0.712359 8 1.091883 0.342883 4 1.047769 -0.215468 5 0.432504 -3.370203 9 0.134519 0.829283 6 -0.001631 -1.385783 3 -0.775563 0.302277 0 -1.370623 -0.091588 1 -1.941154 -0.107553
3.7 Date Function 日期功能扩展了时间序列, 在财务数据分析中起主要作用. 在处理日期数据的同时, 我们经常会遇到以下情况:
3.7.1 pandas.date_range() 通过指定周期和频率, 使用date.range()
函数就可以创建日期序列. 默认情况下, 范围的频率是天.
1 2 3 4 import pandas as pddatelist = pd.date_range('2020/11/21' ,periods=5 ) print(datelist)
输出结果是:
1 2 3 DatetimeIndex(['2020-11-21', '2020-11-22', '2020-11-23', '2020-11-24', '2020-11-25'], dtype='datetime64[ns]', freq='D')
我们可以更改日期频率为月
1 2 3 4 import pandas as pddatelist = pd.date_range('2020/11/21' ,periods=5 , freq='M' ) print(datelist)
输出结果是:
1 2 3 DatetimeIndex(['2020-11-30', '2020-12-31', '2021-01-31', '2021-02-28', '2021-03-31'], dtype='datetime64[ns]', freq='M')
3.7.2 pandas.bdate_range() bdate_range()
用来表示商业日期范围, 不同于date_range()
, 它不包括星期六和星期天.
1 2 3 4 5 6 import pandas as pdstart = pd.datetime(2020 ,8 ,21 ) end = pd.datetime(2020 ,8 ,29 ) datelist = pd.bdate_range(start,end) print(datelist)
输出结果是:
1 2 3 DatetimeIndex(['2020-08-21', '2020-08-24', '2020-08-25', '2020-08-26', '2020-08-27', '2020-08-28'], dtype='datetime64[ns]', freq='B')
参数 freq
可以有以下选择:
3.7.3 pandas.Timedelta() 时间差(Timedelta)是时间上的差异, 以不同的单位来表示. 例如:日, 小时, 分钟, 秒. 它们可以是正值, 也可以是负值. 可以使用各种参数创建Timedelta
对象, 如下所示:
1 2 3 4 import pandas as pdtimediff = pd.Timedelta('2 days 2 hours 15 minues 30 seconds' ) print(timediff)
输出结果是:
以在Series/DataFrames上执行运算操作, 并通过在 datetime64 [ns]
系列或在时间戳上减法操作来构造 timedelta64 [ns]
系列.
1 2 3 4 5 6 7 8 9 10 11 12 13 import pandas as pds = pd.Series(pd.date_range('2012-1-1' , periods=3 , freq='D' )) tdiff = pd.Series([pd.Timedelta(days=i) for i in range (3 )]) df = pd.DataFrame(dict (A=s,B=tdiff)) print('我们的数据是:' ) print(df) print('\n' ) df['A+B' ] = df['A' ] + df['B' ] df['A-B' ] = df['A' ] - df['B' ] print('修改后的数据是:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 我们的数据是: A B 0 2012-01-01 0 days 1 2012-01-02 1 days 2 2012-01-03 2 days 修改后的数据是: A B A+B A-B 0 2012-01-01 0 days 2012-01-01 2012-01-01 1 2012-01-02 1 days 2012-01-03 2012-01-01 2 2012-01-03 2 days 2012-01-05 2012-01-01
3.8 Categorical Data 分类数据 (Categorical Data) 用于表示统计学里有限且唯一性数据集 , 例如描述个人信息的性别一般就男和女两个数据常用’m’和’f’来描述, 有时也能对应编码映射为0和1. 血型A、B、O和AB型等选择可以映射为0、1、2、3这四个数字分别代表各个血型. Pandas 里直接就有 categorical 类型, 可以有效地对数据进行分组进行相应的汇总统计工作.
3.8.1 Object Creation 分类对象可以通过多种方式创建:
通过在pandas
对象创建中将dtype
指定为“category”
.
1 2 3 4 import pandas as pds = pd.Series(['a' ,'b' ,'c' ,'d' ], dtype='category' ) print(s)
输出结果是:
1 2 3 4 5 6 0 a 1 b 2 c 3 d dtype: category Categories (4, object): [a, b, c, d]
使用标准 Pandas 分类构造函数: pandas.Categorical()
. 我们可以创建一个类别对象, 语法如下:
1 2 3 4 5 6 pandas.Categorical(values, categories, ordered)
看个例子
1 2 3 4 import pandas as pdcat = pd.Categorical(values=['a' ,'b' ,'c' ,'d' ,'e' ],categories=['d' ,'b' ,'c' ,'a' ],ordered=True ) print(cat)
输出结果是:
1 2 [a, b, c, d, NaN] Categories (4, object): [d < b < c < a]
3.8.2 Reading Categorical Data
我们可以对分类数据使用 .describe()
, 得到各类数据出现的次数和频率
1 2 3 4 5 import pandas as pdimport numpy as npcat = pd.Categorical(['a' ,'c' ,'a' ,'b' ,'c' ,'b' ,'a' ],categories=['a' ,'b' ,'c' ],ordered=False ) cat.describe()
输出结果是:
我们可以使用 .categories
访问对象的类别, 以及使用 .ordered
看数据是否有排序.
我们还能使用 Categorical.categories
来修改对象的类别
1 2 3 4 5 6 7 8 9 10 import pandas as pdcat = pd.Categorical(['a' ,'c' ,'a' ,'b' ,'c' ,'b' ,'a' ],categories=['a' ,'b' ,'c' ],ordered=False ) print('我们的原数据是:' ) print(cat) print('\n' ) print('修改数据类别' ) cat.categories = ['a' ,'c' ,'e' ] print(cat)
输出结果是
1 2 3 4 5 6 7 8 我们的原数据是: [a, c, a, b, c, b, a] Categories (3, object): [a, b, c] 修改数据类别 [a, e, a, c, e, c, a] Categories (3, object): [a, c, e]
3.8.3 Categorical Data Operations
Adding Categories
使用Categorical.add.categories()
方法, 可以追加新的类别.
1 2 3 4 5 import pandas as pds = pd.Series(['a' ,'b' ,'c' ,'a' ],dtype='category' ) s = s.cat.add_categories(['d' ]) print(s.cat.categories)
输出结果是:
1 Index(['a', 'b', 'c', 'd'], dtype='object')
Removing Categories
使用Categorical.remove_categories()
方法, 可以删除不需要的类别.
1 2 3 4 5 6 7 8 9 import pandas as pds = pd.Series(['a' ,'b' ,'c' ,'a' ],dtype='category' ) print('我们原数据是:' ) print(s) print('\n' ) print('移除类别后:' ) print(s.cat.remove_categories(['a' ]))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 我们原数据是: 0 a 1 b 2 c 3 a dtype: category Categories (3, object): [a, b, c] 移除类别后: 0 NaN 1 b 2 c 3 NaN dtype: category Categories (2, object): [b, c]
Topic 4 Statistics Functions
函数
说明
count()
每一列或行的非空数据的数量
sum()
每一列或行的所有值之和
mean()
每一列或行的所有值的平均值
median()
每一列或行的所有值的中位数
mode()
每一列或行中出现次数最多的数据
std()
每一列或行的标准差
min()
每一列或行的所有值中的最小值
max()
每一列或行的所有值中的最大值
abs()
取绝对值, 只适用于所有数值元素.
prod()
每一列或行的数组元素的乘积
cumsum()
累计总和
cumprod()
累计乘积, 只适用于所有数值元素.
var()
方差
skew()
偏差
kurt()
峰度
quantile()
分位数
cov()
协方差
corr()
相关系数
4.1 DataFrame.count() 每一列非空数据的数量, 用法如下:
1 2 3 4 5 DataFrame.count(self, axis=0 , numeric_only=False )
看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' , 'Lee' ,'David' ,'Gasper' ,'Betina' ,'Andres' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ,34 ,40 ,30 ,51 ,46 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ,3.78 ,2.98 ,4.80 ,4.10 ,3.65 ])} df = pd.DataFrame(d) print('我们的数据是:' ) print(df) print('\n' ) print('非空行的数量:' ) print(df.count())
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 我们的数据是: Name Age Rating 0 Tom 25 4.23 1 James 26 3.24 2 Ricky 25 3.98 3 Vin 23 2.56 4 Steve 30 3.20 5 Minsu 29 4.60 6 Jack 23 3.80 7 Lee 34 3.78 8 David 40 2.98 9 Gasper 30 4.80 10 Betina 51 4.10 11 Andres 46 3.65 非空行的数量: Name 12 Age 12 Rating 12 dtype: int64
4.2 DataFrame.sum() 返回行或列的数据之和, 用法如下:
1 2 3 4 5 6 7 DataFrame.sum (self,axis=None ,skipna=None ,numeric_only=None ,min_count=0 )
看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' , 'Lee' ,'David' ,'Gasper' ,'Betina' ,'Andres' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ,34 ,40 ,30 ,51 ,46 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ,3.78 ,2.98 ,4.80 ,4.10 ,3.65 ])} df = pd.DataFrame(d) print('我们的数据是:' ) print(df) print('\n' ) print('数据类型是数值的列之和:' ) print(df.sum (numeric_only=True ,axis=0 ))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 我们的数据是: Name Age Rating 0 Tom 25 4.23 1 James 26 3.24 2 Ricky 25 3.98 3 Vin 23 2.56 4 Steve 30 3.20 5 Minsu 29 4.60 6 Jack 23 3.80 7 Lee 34 3.78 8 David 40 2.98 9 Gasper 30 4.80 10 Betina 51 4.10 11 Andres 46 3.65 数据类型是数值的列之和: Age 382.00 Rating 44.92 dtype: float64
4.3 DataFrame.mean() 返回数据的平均值, 用法如下:
1 DataFrame.mean(axis=None ,skipna=None ,numeric_only=None )
DataFrame.median()
, DataFrame.std()
, DataFrame.min()
, DataFrame.max()
以及 DataFrame.prod()
…. 的用法与之相同, 我就不再赘述了.
看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' , 'Lee' ,'David' ,'Gasper' ,'Betina' ,'Andres' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ,34 ,40 ,30 ,51 ,46 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ,3.78 ,2.98 ,4.80 ,4.10 ,3.65 ])} df = pd.DataFrame(d) print('我们的数据是:' ) print(df) print('\n' ) print('每列的平均值是:' ) print(df.mean())
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 我们的数据是: Name Age Rating 0 Tom 25 4.23 1 James 26 3.24 2 Ricky 25 3.98 3 Vin 23 2.56 4 Steve 30 3.20 5 Minsu 29 4.60 6 Jack 23 3.80 7 Lee 34 3.78 8 David 40 2.98 9 Gasper 30 4.80 10 Betina 51 4.10 11 Andres 46 3.65 每列的平均值是: Age 31.833333 Rating 3.743333 dtype: float64
4.4 DataFrame.mode() 每一列或行中出现次数最多的数据, 用法如下:
1 2 3 4 5 6 DataFrame.mode(self, axis=0 , numeric_only=False , dropna=True )
看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import pandas as pdimport numpy as npdf = pd.DataFrame([('bird' , 2 , 2 ), ('mammal' , 4 , np.nan), ('arthropod' , 8 , 0 ), ('bird' , 2 , np.nan)], index=('falcon' , 'horse' , 'spider' , 'ostrich' ), columns=('species' , 'legs' , 'wings' )) print('我们的数据是:' ) print(df) print('\n' ) print('dropna 情况下, 每列的 mode:' ) print(df.mode()) print('\n' ) print('不 dropna 的情况下, 每列的 mode:' ) print(df.mode(dropna=False ))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 我们的数据是: species legs wings falcon bird 2 2.0 horse mammal 4 NaN spider arthropod 8 0.0 ostrich bird 2 NaN dropna 情况下, 每列的 mode: species legs wings 0 bird 2.0 0.0 1 NaN NaN 2.0 不 dropna 的情况下, 每列的 mode: species legs wings 0 bird 2 NaN
4.5 DataFrame.abs() 返回一个包含每个元素绝对值的Series
/DataFrame
. 此函数只适用于所有数值元素.
看个列子:
1 2 3 4 5 6 7 8 9 10 11 import numpy as npimport pandas as pddf = pd.DataFrame({'a' : [4 , 5 , 6 , 7 ],'b' : [10 , 20 , 30 , 40 ],'c' : [100 , 50 , -30 , -50 ]}) print('我们的数据是:' ) print(df) print('\n' ) print('取绝对值之后的数据:' ) print(df.abs ())
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 我们的数据是: a b c 0 4 10 100 1 5 20 50 2 6 30 -30 3 7 40 -50 取绝对值之后的数据: a b c 0 4 10 100 1 5 20 50 2 6 30 30 3 7 40 50
4.6 DataFrame.cumsum() & DataFrame.cumprod() 返回DataFrame或Series轴上的累计和/积
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import numpy as npimport pandas as pddf = pd.DataFrame({'a' : [4 , 5 , 6 , 7 ],'b' : [10 , 20 , 30 , 40 ],'c' : [100 , 50 , -30 , -50 ]}) print('我们的数据是:' ) print(df) print('\n' ) print('沿轴 0 累计的和:' ) print(df.cumsum()) print('\n' ) print('沿轴 0 累计的积:' ) print(df.cumprod()) print('\n' )
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 我们的数据是: a b c 0 4 10 100 1 5 20 50 2 6 30 -30 3 7 40 -50 沿轴 0 累计的和: a b c 0 4 10 100 1 9 30 150 2 15 60 120 3 22 100 70 沿轴 0 累计的积: a b c 0 4 10 100 1 20 200 5000 2 120 6000 -150000 3 840 240000 7500000
4.7 DataFrame.describe() 描述性统计归纳总计
1 2 3 4 5 6 7 8 9 10 import pandas as pdd = {'Name' :pd.Series(['Tom' ,'James' ,'Ricky' ,'Vin' ,'Steve' ,'Minsu' ,'Jack' , 'Lee' ,'David' ,'Gasper' ,'Betina' ,'Andres' ]), 'Age' :pd.Series([25 ,26 ,25 ,23 ,30 ,29 ,23 ,34 ,40 ,30 ,51 ,46 ]), 'Rating' :pd.Series([4.23 ,3.24 ,3.98 ,2.56 ,3.20 ,4.6 ,3.8 ,3.78 ,2.98 ,4.80 ,4.10 ,3.65 ])} df = pd.DataFrame(d) print(df.describe())
输出结果是:
1 2 3 4 5 6 7 8 9 Age Rating count 12.000000 12.000000 mean 31.833333 3.743333 std 9.232682 0.661628 min 23.000000 2.560000 25% 25.000000 3.230000 50% 29.500000 3.790000 75% 35.500000 4.132500 max 51.000000 4.800000
4.8 DataFrame.pct_change() Series, DatFrames和Panel都有pct_change()
函数, 此函数将每个元素与其前一个元素进行比较, 并计算变化百分比.
1 2 3 4 5 6 7 import pandas as pdimport numpy as nps = pd.Series([1 ,2 ,3 ,4 ,5 ,4 ]) print (s.pct_change())df = pd.DataFrame(np.random.randn(5 , 2 )) print (df.pct_change())
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 0 NaN 1 1.000000 2 0.500000 3 0.333333 4 0.250000 5 -0.200000 dtype: float64 0 1 0 NaN NaN 1 0.384032 -0.996141 2 -1.736876 679.793981 3 1.063848 -0.441469 4 -1.060066 -1.576158
4.9 DataFrame.sample() 从对象轴返回随机的项目样本, 用法如下:
1 2 3 4 5 6 7 8 9 DataFrame.sample(n=None ,axis=None ,frac=None ,replace=False ,weights=None ,random_state=None )
看个例子:
选取数据的 200% 作为样本, 且允许随机抽样
1 2 3 4 5 6 7 8 9 10 11 import numpy as npimport pandas as pddf = pd.DataFrame({'num_legs' : [2 , 4 , 8 , 0 ], 'num_wings' : [2 , 0 , 0 , 0 ], 'num_specimen_seen' : [10 , 2 , 1 , 8 ]}, index=['falcon' , 'dog' , 'spider' , 'fish' ]) sample = df.sample(frac=2 , replace=True , random_state=1 ) print('我们的样本是:' ) print(sample)
输出结果是:
1 2 3 4 5 6 7 8 9 10 我们的样本是: num_legs num_wings num_specimen_seen dog 4 0 2 fish 0 0 8 falcon 2 2 10 falcon 2 2 10 fish 0 0 8 dog 4 0 2 fish 0 0 8 dog 4 0 2
使用DataFrame列作为权重. num_specimen_seen列中值较大的行更可能被采样.
1 2 3 4 5 6 7 8 9 10 11 import numpy as npimport pandas as pddf = pd.DataFrame({'num_legs' : [2 , 4 , 8 , 0 ], 'num_wings' : [2 , 0 , 0 , 0 ], 'num_specimen_seen' : [10 , 2 , 1 , 8 ]}, index=['falcon' , 'dog' , 'spider' , 'fish' ]) sample = df.sample(frac=2 , replace=True , weights='num_specimen_seen' , random_state=1 ) print('我们的样本是:' ) print(sample)
输出结果是:
1 2 3 4 5 6 7 8 9 10 我们的样本是: num_legs num_wings num_specimen_seen falcon 2 2 10 fish 0 0 8 falcon 2 2 10 falcon 2 2 10 falcon 2 2 10 falcon 2 2 10 falcon 2 2 10 falcon 2 2 10
Topic 5 Data Cleaning 我们先构造一个包含确实数据的 DataFrame
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import pandas as pdimport numpy as npdata = np.arange(10 ,38 ).reshape(7 ,4 ) rows = 'cake make fake sake wake lake take' .split() cols = list ('abcd' ) df = pd.DataFrame(data=data, index=rows, columns=cols) df['e' ] = np.nan df['f' ] = np.nan df.at['make' ,'e' ] = 100 df.at['wake' ,'e' ] = 300 df.loc['jake' ] = np.nan df.at['jake' ,'c' ] = 200 print('我们的数据是:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 我们的数据是: a b c d e f cake 10.0 11.0 12.0 13.0 NaN NaN make 14.0 15.0 16.0 17.0 100.0 NaN fake 18.0 19.0 20.0 21.0 NaN NaN sake 22.0 23.0 24.0 25.0 NaN NaN wake 26.0 27.0 28.0 29.0 300.0 NaN lake 30.0 31.0 32.0 33.0 NaN NaN take 34.0 35.0 36.0 37.0 NaN NaN jake NaN NaN 200.0 NaN NaN NaN
然后, 我们看一下那些列有 NaN 数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import pandas as pdimport numpy as npdata = np.arange(10 ,38 ).reshape(7 ,4 ) rows = 'cake make fake sake wake lake take' .split() cols = list ('abcd' ) df = pd.DataFrame(data=data, index=rows, columns=cols) df['e' ] = np.nan df['f' ] = np.nan df.at['make' ,'e' ] = 100 df.at['wake' ,'e' ] = 300 df.loc['jake' ] = np.nan df.at['jake' ,'c' ] = 200 print('每一列含空数据的情况:' ) print(df.isnull().sum ())
输出结果是:
1 2 3 4 5 6 7 每一列含空数据的情况: a 1 b 1 c 0 d 1 e 6 f 8
5.1 Deleting NaN Data 我们主要使用 dropna()
函数来删除 NaN 数据, 看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import pandas as pdimport numpy as npdata = np.arange(10 ,38 ).reshape(7 ,4 ) rows = 'cake make fake sake wake lake take' .split() cols = list ('abcd' ) df = pd.DataFrame(data=data, index=rows, columns=cols) df['e' ] = np.nan df['f' ] = np.nan df.at['make' ,'e' ] = 100 df.at['wake' ,'e' ] = 300 df.loc['jake' ] = np.nan df.at['jake' ,'c' ] = 200 print('我们的数据是:' ) print(df) print('\n' ) df2 = df.dropna() print('删除含 NaN 的行之后的数据:' ) print(df2)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 我们的数据是: a b c d e f cake 10.0 11.0 12.0 13.0 NaN NaN make 14.0 15.0 16.0 17.0 100.0 NaN fake 18.0 19.0 20.0 21.0 NaN NaN sake 22.0 23.0 24.0 25.0 NaN NaN wake 26.0 27.0 28.0 29.0 300.0 NaN lake 30.0 31.0 32.0 33.0 NaN NaN take 34.0 35.0 36.0 37.0 NaN NaN jake NaN NaN 200.0 NaN NaN NaN 删除含 NaN 的行之后的数据: Empty DataFrame Columns: [a, b, c, d, e, f] Index: []
所有数据都没有了… 这样不是很好, 我们设置 thresh
来设定删除阈值, 看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import pandas as pdimport numpy as npdata = np.arange(10 ,38 ).reshape(7 ,4 ) rows = 'cake make fake sake wake lake take' .split() cols = list ('abcd' ) df = pd.DataFrame(data=data, index=rows, columns=cols) df['e' ] = np.nan df['f' ] = np.nan df.at['make' ,'e' ] = 100 df.at['wake' ,'e' ] = 300 df.loc['jake' ] = np.nan df.at['jake' ,'c' ] = 200 print('我们的数据是:' ) print(df) print('\n' ) print('列上至少有两个非 NaN 的列留下:' ) df2 = df.dropna(axis='columns' , thresh=2 ) print(df2)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 我们的数据是: a b c d e f cake 10.0 11.0 12.0 13.0 NaN NaN make 14.0 15.0 16.0 17.0 100.0 NaN fake 18.0 19.0 20.0 21.0 NaN NaN sake 22.0 23.0 24.0 25.0 NaN NaN wake 26.0 27.0 28.0 29.0 300.0 NaN lake 30.0 31.0 32.0 33.0 NaN NaN take 34.0 35.0 36.0 37.0 NaN NaN jake NaN NaN 200.0 NaN NaN NaN 列上至少有两个非 NaN 的列留下: a b c d e cake 10.0 11.0 12.0 13.0 NaN make 14.0 15.0 16.0 17.0 100.0 fake 18.0 19.0 20.0 21.0 NaN sake 22.0 23.0 24.0 25.0 NaN wake 26.0 27.0 28.0 29.0 300.0 lake 30.0 31.0 32.0 33.0 NaN take 34.0 35.0 36.0 37.0 NaN jake NaN NaN 200.0 NaN NaN
5.2 Filling NaN Data 我们主要是用 DataFrame.fillna()
函数对缺失值进行填充, 有这么几种方法:
使用 0 (或任意值) 填充缺失值
df.fillna(0)
用一个字符串来代替缺失值
df.fillna('missing')
用前一个数据代替缺失值
df.fillna(method='pad')
用后一个数据替代缺失值, 我们可以设置 limit 参数来限制替代缺失值的次数
df.fillna(method='bfill', limit=2)
我们还可以使用描述性统计量来代替缺失值
df.fillna(df.mean())
我们还可以指定某一列的描述性统计量来填充所有缺失值
df.fillna(df.mean()['e'])
5.3 Deleting Duplicated Data 我们可以首先使用 DataFrame.duplicated()
来查看 DataFrame 中是否存在重复的数据. 然后再使用 DataFrame.drop_duplicates()
来移除重复数据. 看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import numpy as npimport pandas as pdfruit = ["apple" , "pearl" , "watermelon" ] * 4 price = [2.50 , 3.00 , 2.75 ] * 4 df = pd.DataFrame({"fruit" : fruit, "price" : price}) print('我们的数据是:' ) print(df) print('\n' ) print('查看数据重复情况:' , df.duplicated().sum ()) print(df.duplicated()) print('\n' ) print('移除重复数据:' ) print(df.drop_duplicates())
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 我们的数据是: fruit price 0 apple 2.50 1 pearl 3.00 2 watermelon 2.75 3 apple 2.50 4 pearl 3.00 5 watermelon 2.75 6 apple 2.50 7 pearl 3.00 8 watermelon 2.75 9 apple 2.50 10 pearl 3.00 11 watermelon 2.75 查看数据重复情况: 9 0 False 1 False 2 False 3 True 4 True 5 True 6 True 7 True 8 True 9 True 10 True 11 True 移除重复数据: fruit price 0 apple 2.50 1 pearl 3.00 2 watermelon 2.75
DataFrame
里的数据未必是原始数据, 例如采集时设定了一些协议, 1代表某某、2代表另一个事务或内容, 那么当开发者得到这些协议后的编码, 需要做一些数据上的变换, 以便真实的反映数据本身.
5.4.1 Series.map() map()
是一个 Series 的函数,DataFrame结构中没有map(). map()
将一个自定义函数应用于 Series 结构中的每个元素(elements). 我们看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import pandas as pdimport numpy as npdf = pd.DataFrame({'key1' : ['a' , 'a' , 'b' , 'b' , 'a' ], 'key2' : ['one' , 'two' , 'one' , 'two' , 'one' ], 'data1' : np.arange(5 ), 'data2' : np.arange(5 ,10 )}) print('我们的数据是:' ) print(df) print('\n' ) print('我们现在用map来对列 data1 改成保留小数点后三位' ) df['data1' ] = df['data1' ].map (lambda x: '%.3f' %x) print('用map把key1的a改成c,b改成d' ) df['key1' ] = df['key1' ].map ({'a' :'c' ,'b' :'d' }) print('\n' ) print('修改后的数据是:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 我们的数据是: key1 key2 data1 data2 0 a one 0 5 1 a two 1 6 2 b one 2 7 3 b two 3 8 4 a one 4 9 我们现在用map来对列 data1 改成保留小数点后三位 用map把key1的a改成c,b改成d 修改后的数据是: key1 key2 data1 data2 0 c one 0.000 5 1 c two 1.000 6 2 d one 2.000 7 3 d two 3.000 8 4 c one 4.000 9
5.4.2 DataFrame.replace() 之前我们将的 fillna()
函数可以将NaN数据填充为0,这里的replace函数可以将数据替换成其他数据. replace函数的使用方式有很多, 可以一对一的替换也可一对多的替换数据. 用法如下:
1 2 3 4 5 6 7 8 DataFrame.replace(self, to_replace=None , value=None , inplace=False , limit=None , regex=False , method='pad' )
我们看一个正则表达式的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pandas as pdimport numpy as npdf = pd.DataFrame({'A' : ['bat' , 'foo' , 'bait' ], 'B' : ['abc' , 'bar' , 'xyz' ]}) print('我们的数据是:' ) print(df) print('\n' ) print('替换后的数据是:' ) df1 = df.replace(to_replace=r'^ba.$' ,value='new' ,regex=True ) print(df1) df1 = df.replace(regex=r'^ba.$' , value='new' ) df1 = df.replace(regex={r'^ba.$' : 'new' , 'foo' : 'xyz' }) df1 = df.replace(regex=[r'^ba.$' , 'foo' ], value='new' )
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 我们的数据是: A B 0 bat abc 1 foo bar 2 bait xyz 替换后的数据是: A B 0 new abc 1 foo new 2 bait xyz
5.4.3 DataFrame.apply() apply()
将一个函数作用于DataFrame中的每个行或者列, 看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import pandas as pdimport numpy as npdf = pd.DataFrame({'key1' : ['a' , 'a' , 'b' , 'b' , 'a' ], 'key2' : ['one' , 'two' , 'one' , 'two' , 'one' ], 'data1' : np.arange(5 ), 'data2' : np.arange(5 ,10 )}) print('我们的数据是:' ) print(df) print('\n' ) print('使用 apply() 求每列的和' ) print('使用 apply() 对列 data1, data2 进行相加' ) df.loc['total' ] = df[['data1' ,'data2' ]].apply(lambda x: x.sum (), axis=0 ) df['total' ] = df[['data1' ,'data2' ]].apply(lambda x: x.sum (), axis=1 ) print('\n' ) print('修改之后的数据:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 我们的数据是: key1 key2 data1 data2 0 a one 0 5 1 a two 1 6 2 b one 2 7 3 b two 3 8 4 a one 4 9 使用 apply() 求每列的和 使用 apply() 对列 data1, data2 进行相加 修改之后的数据: key1 key2 data1 data2 total 0 a one 0.0 5.0 5.0 1 a two 1.0 6.0 7.0 2 b one 2.0 7.0 9.0 3 b two 3.0 8.0 11.0 4 a one 4.0 9.0 13.0 total NaN NaN 10.0 35.0 45.0
5.4.5 DataFrame.applymap() 将函数作用于 DataFrame 中的所有元素(elements), 看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pandas as pdimport numpy as npdf = pd.DataFrame({'key1' : ['a' , 'a' , 'b' , 'b' , 'a' ], 'key2' : ['one' , 'two' , 'one' , 'two' , 'one' ], 'data1' : np.arange(5 ), 'data2' : np.arange(5 ,10 )}) print('我们的数据是:' ) print(df) print('\n' ) def addA (x ): return 'A' + str (x) df2 = df.applymap(addA) print('修改后的数据是:' ) print(df2)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 我们的数据是: key1 key2 data1 data2 0 a one 0 5 1 a two 1 6 2 b one 2 7 3 b two 3 8 4 a one 4 9 修改后的数据是: key1 key2 data1 data2 0 Aa Aone A0 A5 1 Aa Atwo A1 A6 2 Ab Aone A2 A7 3 Ab Atwo A3 A8 4 Aa Aone A4 A9
5.5 Data Concatenation 这里主要有两个函数:
DataFrame.concat()
DataFrame.merge()
5.5.1 pandas.concat() concat()
函数的用法如下:
1 2 3 4 5 6 7 8 9 pandas.concat(objs, axis=0 , join='outer' , join_axes=None , ignore_index=False , keys=None , names=None , verify_integrity=False )
我们竖直拼接的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import numpy as npimport pandas as pddf1 = pd.DataFrame({'A' :['A0' ,'A1' ,'A2' ,'A3' ], 'B' :['B0' ,'B1' ,'B2' ,'B3' ], 'C' :['C0' ,'C1' ,'C2' ,'C3' ], 'D' :['D0' ,'D1' ,'D2' ,'D3' ]}, index=[0 ,1 ,2 ,3 ]) df2 = pd.DataFrame({'A' :['A4' ,'A5' ,'A6' ,'A7' ], 'B' :['B4' ,'B5' ,'B6' ,'B7' ], 'C' :['C4' ,'C5' ,'C6' ,'C7' ], 'D' :['D4' ,'D5' ,'D6' ,'D7' ]}, index=[4 ,5 ,6 ,7 ]) df3 = pd.DataFrame({'A' :['A8' ,'A9' ,'A10' ,'A11' ], 'B' :['B8' ,'B9' ,'B10' ,'B11' ], 'C' :['C8' ,'C9' ,'C10' ,'C11' ], 'D' :['D8' ,'D9' ,'D10' ,'D11' ]}, index=[8 ,9 ,10 ,11 ]) print('我们的三个 DataFrame 分别是:' ) print(df1) print() print(df2) print() print(df3) print('\n' ) print('我们竖直拼接三个 DataFrame, 并指明其来源:' ) print(pd.concat([df1,df2,df3], axis=0 , keys=['df1' ,'df2' ,'df3' ]))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 我们的三个 DataFrame 分别是: A B C D 0 A0 B0 C0 D0 1 A1 B1 C1 D1 2 A2 B2 C2 D2 3 A3 B3 C3 D3 A B C D 4 A4 B4 C4 D4 5 A5 B5 C5 D5 6 A6 B6 C6 D6 7 A7 B7 C7 D7 A B C D 8 A8 B8 C8 D8 9 A9 B9 C9 D9 10 A10 B10 C10 D10 11 A11 B11 C11 D11 我们竖直拼接三个 DataFrame, 并指明其来源: A B C D df1 0 A0 B0 C0 D0 1 A1 B1 C1 D1 2 A2 B2 C2 D2 3 A3 B3 C3 D3 df2 4 A4 B4 C4 D4 5 A5 B5 C5 D5 6 A6 B6 C6 D6 7 A7 B7 C7 D7 df3 8 A8 B8 C8 D8 9 A9 B9 C9 D9 10 A10 B10 C10 D10 11 A11 B11 C11 D11
我们看一个水平拼接的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import numpy as npimport pandas as pddf1 = pd.DataFrame({'A' :['A0' ,'A1' ,'A2' ,'A3' ], 'B' :['B0' ,'B1' ,'B2' ,'B3' ], 'C' :['C0' ,'C1' ,'C2' ,'C3' ], 'D' :['D0' ,'D1' ,'D2' ,'D3' ]}, index=[0 ,1 ,2 ,3 ]) df2 = pd.DataFrame({'A1' :['A4' ,'A5' ,'A6' ,'A7' ], 'B2' :['B4' ,'B5' ,'B6' ,'B7' ], 'C2' :['C4' ,'C5' ,'C6' ,'C7' ], 'D2' :['D4' ,'D5' ,'D6' ,'D7' ]}, index=[0 ,1 ,2 ,3 ]) df3 = pd.DataFrame({'A3' :['A8' ,'A9' ,'A10' ,'A11' ], 'B3' :['B8' ,'B9' ,'B10' ,'B11' ], 'C3' :['C8' ,'C9' ,'C10' ,'C11' ], 'D3' :['D8' ,'D9' ,'D10' ,'D11' ]}, index=[0 ,1 ,2 ,3 ]) print('我们的三个 DataFrame 分别是:' ) print(df1) print() print(df2) print() print(df3) print('\n' ) print('我们水平拼接三个 DataFrame, 并指明其来源:' ) print(pd.concat([df1,df2,df3], axis=1 , keys=['df1' ,'df2' ,'df3' ]))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 我们的三个 DataFrame 分别是: A B C D 0 A0 B0 C0 D0 1 A1 B1 C1 D1 2 A2 B2 C2 D2 3 A3 B3 C3 D3 A1 B2 C2 D2 0 A4 B4 C4 D4 1 A5 B5 C5 D5 2 A6 B6 C6 D6 3 A7 B7 C7 D7 A3 B3 C3 D3 0 A8 B8 C8 D8 1 A9 B9 C9 D9 2 A10 B10 C10 D10 3 A11 B11 C11 D11 我们水平拼接三个 DataFrame, 并指明其来源: df1 df2 df3 A B C D A1 B2 C2 D2 A3 B3 C3 D3 0 A0 B0 C0 D0 A4 B4 C4 D4 A8 B8 C8 D8 1 A1 B1 C1 D1 A5 B5 C5 D5 A9 B9 C9 D9 2 A2 B2 C2 D2 A6 B6 C6 D6 A10 B10 C10 D10 3 A3 B3 C3 D3 A7 B7 C7 D7 A11 B11 C11 D11
5.5.2 pandas.merge() concat函数可以实现内外连接, 而pandas的merge函数可以真正实现数据库的内外连接, 且外连接还可以有左右连接的特性. 用法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 pandas.merge(left, right, how='inner' , on=None , left_on=None , right_on=None , left_index=False , right_index=False , sort=True , suffixes=('_x' ,'_y' ), copy=True , indicator=False )
我们看一个简单的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import pandas as pdleft = 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' ]}) result = pd.merge(left, right, on='key' ) print('左表是:' ) print(left) print('\n' ) print('右表示:' ) print(right) print('\n' ) print('拼接结果是:' ) print(result)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 左表是: key A B 0 K0 A0 B0 1 K1 A1 B1 2 K2 A2 B2 3 K3 A3 B3 右表是: key C D 0 K0 C0 D0 1 K1 C1 D1 2 K2 C2 D2 3 K3 C3 D3 拼接结果是: key A B C D 0 K0 A0 B0 C0 D0 1 K1 A1 B1 C1 D1 2 K2 A2 B2 C2 D2 3 K3 A3 B3 C3 D3
传入的 on 也可以是列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import pandas as pdleft = pd.DataFrame({'key1' : ['K0' , 'K0' , 'K1' , 'K2' ], 'key2' : ['K0' , 'K1' , 'K0' , 'K1' ], 'A' : ['A0' , 'A1' , 'A2' , 'A3' ], 'B' : ['B0' , 'B1' , 'B2' , 'B3' ]}) right = pd.DataFrame({'key1' : ['K0' , 'K1' , 'K1' , 'K2' ], 'key2' : ['K0' , 'K0' , 'K0' , 'K0' ], 'C' : ['C0' , 'C1' , 'C2' , 'C3' ], 'D' : ['D0' , 'D1' , 'D2' , 'D3' ]}) result = pd.merge(left, right, on=['key1' ,'key2' ]) print('左表是:' ) print(left) print('\n' ) print('右表是:' ) print(right) print('\n' ) print('拼接结果是:' ) print(result)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 左表是: key1 key2 A B 0 K0 K0 A0 B0 1 K0 K1 A1 B1 2 K1 K0 A2 B2 3 K2 K1 A3 B3 右表是: key1 key2 C D 0 K0 K0 C0 D0 1 K1 K0 C1 D1 2 K1 K0 C2 D2 3 K2 K0 C3 D3 拼接结果是: key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K1 K0 A2 B2 C1 D1 2 K1 K0 A2 B2 C2 D2
左外连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import pandas as pdleft = pd.DataFrame({'key1' : ['K0' , 'K0' , 'K1' , 'K2' ], 'key2' : ['K0' , 'K1' , 'K0' , 'K1' ], 'A' : ['A0' , 'A1' , 'A2' , 'A3' ], 'B' : ['B0' , 'B1' , 'B2' , 'B3' ]}) right = pd.DataFrame({'key1' : ['K0' , 'K1' , 'K1' , 'K2' ], 'key2' : ['K0' , 'K0' , 'K0' , 'K0' ], 'C' : ['C0' , 'C1' , 'C2' , 'C3' ], 'D' : ['D0' , 'D1' , 'D2' , 'D3' ]}) result = pd.merge(left, right, how='left' , on=['key1' ,'key2' ]) print('左表是:' ) print(left) print('\n' ) print('右表是:' ) print(right) print('\n' ) print('拼接结果是:' ) print(result)
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 左表是: key1 key2 A B 0 K0 K0 A0 B0 1 K0 K1 A1 B1 2 K1 K0 A2 B2 3 K2 K1 A3 B3 右表是: key1 key2 C D 0 K0 K0 C0 D0 1 K1 K0 C1 D1 2 K1 K0 C2 D2 3 K2 K0 C3 D3 拼接结果是: key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K0 K1 A1 B1 NaN NaN 2 K1 K0 A2 B2 C1 D1 3 K1 K0 A2 B2 C2 D2 4 K2 K1 A3 B3 NaN NaN
5.6.1 DataFrame.pivot() 返回按给定索引/列以及制定的列值 的重新构造的 pivot table
. 如果作为 columns
的列具有重复值, 那么在使用 pivot
函数的时候就会报错, 此时我们需要使用DataFrame.pivot_table
.
DataFrame.pivot()
的用法如下:
1 2 3 4 5 6 DataFrame.pivot(self, index=None , columns=None , values=None )
看个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pandas as pdimport numpy as npdf = pd.DataFrame({'foo' : ['one' , 'one' , 'one' , 'two' , 'two' , 'two' ], 'bar' : ['A' , 'B' , 'C' , 'A' , 'B' , 'C' ], 'baz' : [1 , 2 , 3 , 4 , 5 , 6 ], 'zoo' : ['x' , 'y' , 'z' , 'q' , 'w' , 't' ]}) print('我们的数据是:' ) print(df) print('\n' ) print('使用 pivot 函数:' ) print(df.pivot(index='foo' , columns='bar' ))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 我们的数据是: foo bar baz zoo 0 one A 1 x 1 one B 2 y 2 one C 3 z 3 two A 4 q 4 two B 5 w 5 two C 6 t 使用 pivot 函数: baz zoo bar A B C A B C foo one 1 2 3 x y z two 4 5 6 q w t
5.6.2 DataFrame.pivot_table() 与 pivot
相比,该方法可以汇总多个重复条目的数据. 我们可以用均值、中位数或者其他汇总函数来计算重复条目的数值. pivot_table
方法需要传递一个新的参数 aggfunc
, 该参数用于指明转换时所需的汇总函数. 我们看个图解:
该函数的用法如下
1 2 3 4 5 6 7 8 9 DataFrame.pivot_table(self, index=None , columns=None , values=None , aggfunc='mean' , fill_value=None , margins=False , dropna=True , margins_name='All' , observed=False )
我们来看一个 NBA 的例子, 先读取数据
1 2 3 4 5 import pandas as pdimport numpy as npdf = pd.read_csv('James_Harden.csv' ,encoding='utf-8' ) df.head()
输出结果是:
然后我们看一下哈登对阵每个队伍的情况
1 df.pivot_table(index=u'对手' ).head()
输出结果是:
让我们继续深入, 不同对手以及主客场情况下的得分概况
1 df.pivot_table(index=[u'对手' ,u'主客场' ])
输出结果是:
看完上面几个操作, Index就是层次字段, 要通过透视表获取什么信息就按照相应的顺序设置字段,所以在进行pivot之前你也需要足够了解你的数据.
当我们未设置 aggfunc
时, 它默认 aggfunc='mean'
计算均值. 我们还想要获得james harden在主客场和不同胜负情况下的总得分、总篮板、总助攻概况
1 df.pivot_table(index=[u'主客场' ,u'胜负' ],values=[u'得分' ,u'助攻' ,u'篮板' ],aggfunc=[np.sum ,np.mean])
输出结果是:
Columns类似Index可以设置列层次字段, 它不是一个必要参数, 作为一种分割数据的可选方式.
1 df.pivot_table(index=[u'主客场' ],columns=[u'对手' ],values=[u'得分' ],aggfunc=[np.sum ],fill_value=0 ,margins=1 )
输出结果是:
最后看一个综合的例子
1 df.pivot_table(index=[u'对手' ,u'胜负' ],columns=[u'主客场' ],values=[u'得分' ,u'助攻' ,u'篮板' ],aggfunc=[np.mean],fill_value=0 ).head()
输出结果是:
5.7 Aggregating Data 5.7.1 DataFrame.groupby() 在SQL语言里有group by功能,在Pandas里有groupby函数与之功能相对应. DataFrame数据对象经groupby()之后返回的结果是一个 DataFrameGroupBy
对象, 而不是一个 DataFrame
或者 Series
对象, 所以, 它们中的一些方法或者函数是无法直接调用的, 需要按照 GroupBy
对象中具有的函数和方法进行调用.
ngroups
反应的是分组的个数
groups
类似 dict 结构
size()
则是可以返回所有分组的数据个数.
count()
可以统计分组后各列数据项个数
get_group()
可以返回指定组的数据信息
discribe()
可以返回分组后的数据的统计数据
我们创建一个 DataFrame
1 2 3 4 5 6 7 8 9 10 11 import numpy as npimport pandas as pdname = ['Alen' ,'Bob' ,'Cidy' ,'Daniel' ,'Ellen' ,'Frankie' ,'Gate' ,'Hebe' ] gender = ['Male' ,'Male' ,'Female' ,'Male' ,'Female' ,'Male' ,'Male' ,'Female' ] age = [18 ,19 ,18 ,20 ,17 ,21 ,20 ,22 ] score = [80 ,90 ,93 ,87 ,96 ,100 ,88 ,98 ] df = pd.DataFrame(data={'Name' :name,'Gender' :gender,'Age' :age,'Score' :score}) print('我们的数据是:' ) print(df)
输出结果是:
1 2 3 4 5 6 7 8 9 10 我们的数据是: Name Gender Age Score 0 Alen Male 18 80 1 Bob Male 19 90 2 Cidy Female 18 93 3 Daniel Male 20 87 4 Ellen Female 17 96 5 Frankie Male 21 100 6 Gate Male 20 88 7 Hebe Female 22 98
我们使用 groupby()
函数
1 2 3 grouped = df.groupby('Gender' ) print(type (grouped)) print(grouped)
输出结果是:
1 2 <class 'pandas.core.groupby.generic.DataFrameGroupBy'> <pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fb650d31490>
分组时, 不仅仅可以指定一个列名, 也可以指定多个列名
1 2 3 4 5 6 grouped = df.groupby('Gender' ) grouped_muti = df.groupby(['Gender' , 'Age' ]) print(grouped.size()) print('\n' ) print(grouped_muti.size())
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Gender Female 3 Male 5 dtype: int64 Gender Age Female 17 1 18 1 22 1 Male 18 1 19 1 20 2 21 1 dtype: int64
指定多个列名个单个列名后的区别在于, 分组的索引 (index) 将一个是单个主键, 另一个则是一个元组的形式
1 2 3 4 5 6 a = grouped.get_group('Female' ) b = grouped_muti.get_group(('Female' ,17 )) print(a) print('\n' ) print(b)
输出结果是:
1 2 3 4 5 6 7 8 Name Age Score 2 Cidy 18 93 4 Ellen 17 96 7 Hebe 22 98 Name Gender Age Score 4 Ellen Female 17 96
注: 通过调用get_group()
函数可以返回一个按照分组得到的DataFrame
对象, 所以接下来的使用就可以按照·DataFrame·对象来使用. 如果想让这个DataFrame
对象的索引重新定义可以通过:
1 print(grouped.get_group('Female' ).reset_index())
输出结果是:
1 2 3 4 index Name Age Score 0 2 Cidy 18 93 1 4 Ellen 17 96 2 7 Hebe 22 98
5.7.2 DataFrame.agg()
在对数据进行分组之后, 可以对分组后的数据进行聚合处理统计. 用法如下:
1 2 3 4 5 6 7 8 9 DataFrame.agg(func, axis=0 , *args, **kwargs)
看个例子, 求 age 和 score 的 mean 和 sum
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import numpy as npimport pandas as pdname = ['Alen' ,'Bob' ,'Cidy' ,'Daniel' ,'Ellen' ,'Frankie' ,'Gate' ,'Hebe' ] gender = ['Male' ,'Male' ,'Female' ,'Male' ,'Female' ,'Male' ,'Male' ,'Female' ] age = [18 ,19 ,18 ,20 ,17 ,21 ,20 ,22 ] score = [80 ,90 ,93 ,87 ,96 ,100 ,88 ,98 ] df = pd.DataFrame(data={'Name' :name,'Gender' :gender,'Age' :age,'Score' :score}) print('我们的数据是:' ) print(df) print('\n' ) print('使用 agg 函数:' ) print(df.agg({'Age' :['sum' ,'mean' ],'Score' :['sum' ,'mean' ]})) print('\n' ) print('我们也可以使用自定义的 lambda 函数:' ) get_max = lambda x: x.sort_values(ascending=False ).iloc[0 ] get_max.__name__ = 'get_max' print(df.agg({'Age' :[get_max],'Score' :[get_max]}))
输出结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 我们的数据是: Name Gender Age Score 0 Alen Male 18 80 1 Bob Male 19 90 2 Cidy Female 18 93 3 Daniel Male 20 87 4 Ellen Female 17 96 5 Frankie Male 21 100 6 Gate Male 20 88 7 Hebe Female 22 98 使用 agg 函数: Age Score sum 155.000 732.0 mean 19.375 91.5 我们也可以使用自定义的 lambda 函数: Age Score get_max 22 100
调用func
自己产生一个改变值的和自己的相同的轴长度的DataFrame
.
直接看例子:
假设我们有下面的销售数据 , 有三个不同的 订单id (10001, 10005和10006), 每个 订单id又含有多个产品.
1 2 3 4 5 6 import pandas as pdimport numpy as npdf = pd.read_excel('sales_transactions.xlsx' ) print('我们的数据是:' ) print(df)
输出结果是:
我们现在要求解的问题是: 每个订单中各个单品费用分布及占比 . 例如订单10001总价$576.12,细分一下:
1 2 3 B1-20000 = $235.83 or 40.9% S1-27722 = $232.32 or 40.3% B1-86481 = $107.97 or 18.7%
解决这个问题用两种方式:
第一种新建 DataFrame 然后 merge 两个 DataFrame. 代码如下:
1 2 3 4 5 6 7 8 9 10 11 order_total = df.groupby('order' )["ext price" ].sum ().rename("Order_Total" ).reset_index() df_1 = df.merge(order_total) df_1["Percent_of_Order" ] = df_1["ext price" ] / df_1["Order_Total" ] print('新建的 DataFrame 是:' ) print(order_total) print('\n' ) print('我们的结果是:' ) print(df_1)
输出结果是:
新建的 DataFrame 是:
我们的结果是:
第二种就是使用 DataFrame.transform()
这个函数:
1 2 3 4 5 6 7 8 import pandas as pdimport numpy as npdf = pd.read_excel('sales_transactions.xlsx' ) df["Percent_of_Order" ] = df["ext price" ] / df.groupby('order' )["ext price" ].transform('sum' ) print('我们的结果是:' ) print(df)
输出结果是:
我们的结果是:
Topic 6 Pandas IO 平时工作中, 我们会接触到不同的数据文件, 比如很常见的excel文件(后缀名为xls和xlsx), csv、txt等文本文件, json文件以及sql文件等等. pandas读取这些数据文件的方法如表格所示:
读取方法
描述
写入方法
read_csv
读取 csv 文件, 逗号是默认分隔符
to_csv
read_table
读取通用分隔符分割的数据文件, 默认为制表符 \t
to_csv
read_excel
读取 xls
或者 xlsx
表格文件
to_excel
read_json
读取 json
文件
to_json
read_sql
从 SQL 请求读取或者读取数据库中的表
to_sql
read_sql_table
读取数据库中的表
to_sql
read_sql_query
从 SQL 请求读取数据
to_sql
6.1 pandas.read_csv() read_csv()方法用来读取 csv格式的数据文件, read_table()方法则是读取通用分隔符分隔的数据文件 , 它们的参数相同, 语法如下:
1 2 3 4 5 6 7 8 9 10 11 pandas.read_csv(filepath_or_buffer, sep=',' , delimiter=None , header='infer' , names=None , index_col=None , usecols=None , skiprows=None )