Pandas简介
Pandas 是python的一个数据分析包,pandas是一款数据处理工具,集成了numpy以及matplotlib,拥有便捷的数据处理以及文件读取能力
Pandas 提供了三种数据对象,分别是 Series、 DataFrame 和 Panel。 其中 , Series 用于保存 一维类的数据, DataFrame 用于保存二维类的数据, Panel 用于保存三维类或者可变维度的数据。 在通常的数据分析中,我们经常使用 Series 和 DataFrame 这两种类型的数据,所以这两种类型 要重点介绍。
数据结构
Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
Time- Series:以时间为索引的Series。
DataFrame:DataFrame是⼀个二维的表格型数据结构,它含有⼀组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有⾏索引也有列索引,它可以被看做由Series组成的字典(共⽤同⼀个索引)。DataFrame中的数据是以⼀个或多个⼆维块存放的(⽽不是列表、字典或别的⼀维数据结构)。
Panel :三维的数组,可以理解为DataFrame的容器。
Pandas 有两种自己独有的基本数据结构。读者应该注意的是,它固然有着两种数据结构,因为它依然是 Python 的一个库,所以,Python 中有的数据类型在这里依然适用,也同样还可以使用类自己定义数据类型。只不过,Pandas 里面又定义了两种数据类型:Series 和 DataFrame,它们让数据操作更简单了。
Series 对象
可理解为带索引的一维数组
创建 Series 对象
创建 Series 对象就是建立 Series 类的实例,其完整的参数列表是:
pd.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
- data: 可以是数组、列表等类数组对象,也可以是字典,还可以是一个数字、字符串 。
- index: Series 对象的索引,如果为 None,则按照默认的从 0 开始的整数进行索引 。注 意 index 值的长度和 data 值的长度应该相同。
import numpy as np
import pandas as pd
g = np.array([27466.15, 24899.3, 19610.9, 19492.4, 17885.39, 17558.76, 15475.09, 12179.2])
print(g)
gdp = pd.Series(g, index=['shanghai', 'beijing', 'guangzhou', 'shenzhen', 'tianjin','chongqing', 'suzhou', 'chengdu'])
print(gdp)
输出:
[27466.15 24899.3 19610.9 19492.4 17885.39 17558.76 15475.09 12179.2 ]
shanghai 27466.15
beijing 24899.30
guangzhou 19610.90
shenzhen 19492.40
tianjin 17885.39
chongqing 17558.76
suzhou 15475.09
chengdu 12179.20
dtype: float64
a = pd.Series(data=[100, 200, 300])
print(a)
输出:
0 100
1 200
2 300
dtype: int64
a = pd.Series(100, index=['a', 'b', 'c'])
print(a)
输出:
a 100
b 100
c 100
dtype: int64
a = pd.Series({'wuhan':11912.6, 'hangzhou':11050.5, 'nanjing':10503})
print(a)
print('*********************')
a = pd.Series({'wuhan':11912.6, 'hangzhou':11050.5, 'nanjing':10503}, index=['nanjing','wuhan','hangzhou'])
print(a)
输出:
wuhan 11912.6
hangzhou 11050.5
nanjing 10503.0
dtype: float64
*********************
nanjing 10503.0
wuhan 11912.6
hangzhou 11050.5
dtype: float64
Series 对象属性
对于每个 Series 对象,都有 index 和 values 两个基本属性,可以分别获得标签索引和元素。
- index—— 索引项
- values——索引值,numpy.ndarray类型
a = pd.Series({'wuhan':11912.6, 'hangzhou':11050.5, 'nanjing':10503})
print(a)
print(a.index)
print(a.values)
输出:
wuhan 11912.6
hangzhou 11050.5
nanjing 10503.0
dtype: float64
Index(['wuhan', 'hangzhou', 'nanjing'], dtype='object')
[11912.6 11050.5 10503. ]
DataFrame
numpy仅用作计算,在数据表示方面还有所欠缺,很难从数据上面看出信息表达的含义,在这里我们可以将DataFrame看作是有行列索引(标题)的二维数组
Series 对象用于存储一维数据, DataFrame 专门用于存储二维数据。
创建 DataFrame 对象
在 Pandas 中,通过实例化 pd.DataFrame()创建 DataFrame 对象
pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
- data:可以是嵌套列表、 二维数组、字典或者 DataFrame 对象。字典中的数据除字符串、 数字等基本的 Python 数据类型外,还可以包括 Series、 数组等序列类型的对象。
- index: 可以是索引对象或者类数组对象。当然,跟 Series 类似,如果 index 为 None, 则按照默认的 0、 l 、 2……顺序建立索引。
- columns: 可以是索引对象或者类数组对象。其含义是列 索引 。 如果用数据库或者电子表格中的术语,则可以叫作“字段”。
下面就通过示例从不同侧面理解创建 DataFrame 对象的基本方法。
import pandas as pd
gp = pd.DataFrame([[27466.15, 2419.70], [24899.30, 2172.90],
[19610.90, 1350.11], [19492.60, 1137.87],
[17885.39, 1562.12], [17558.76, 3016.55],
[15475.09, 1375.00], [12170.20, 1591.76]])
print(gp)
输出:
0 1
0 27466.15 2419.70
1 24899.30 2172.90
2 19610.90 1350.11
3 19492.60 1137.87
4 17885.39 1562.12
5 17558.76 3016.55
6 15475.09 1375.00
7 12170.20 1591.76
没有向 index 和 columns 两个参数传入值,就用从 0 开始 计数的整数表示相应索引 。
与 Series 对象类似, 也能够通过 DataFrame 对象的 index 和 columns 两个属性为其设置 “标签索引”。
import pandas as pd
gp = pd.DataFrame([[27466.15, 2419.70], [24899.30, 2172.90],
[19610.90, 1350.11], [19492.60, 1137.87],
[17885.39, 1562.12], [17558.76, 3016.55],
[15475.09, 1375.00], [12170.20, 1591.76]])
gp.index =['SHANGHAI','BEIJING ','GUANGZHOU', 'CHONGQING ','SUZHOU', 'CHENGDU', 'WH', 'HAH']
gp.columns =['GDP', 'Population']
print(gp)
输出:
GDP Population
SHANGHAI 27466.15 2419.70
BEIJING 24899.30 2172.90
GUANGZHOU 19610.90 1350.11
CHONGQING 19492.60 1137.87
SUZHOU 17885.39 1562.12
CHENGDU 17558.76 3016.55
WH 15475.09 1375.00
HAH 12170.20 1591.76
如果在创建 DataFrame 对象的时候,给 index 和 columns 传入参数,则可以用如下方式。
import pandas as pd
gp = pd.DataFrame([[27466.15, 2419.70], [24899.30, 2172.90],
[19610.90, 1350.11], [19492.60, 1137.87],
[17885.39, 1562.12], [17558.76, 3016.55]],
index = ['SHANGHAI', 'BEIJING ', 'GUANGZHOU', 'CHONGQING ', 'SUZHOU', 'CHENGDU'],
columns=['GDP', 'Population']
)
print(gp)
输出:
GDP Population
SHANGHAI 27466.15 2419.70
BEIJING 24899.30 2172.90
GUANGZHOU 19610.90 1350.11
CHONGQING 19492.60 1137.87
SUZHOU 17885.39 1562.12
CHENGDU 17558.76 3016.55
还有与 Series 对象类似的操作,可以分别给 index 和 columns 命名
import pandas as pd
gp = pd.DataFrame([[27466.15, 2419.70], [24899.30, 2172.90],
[19610.90, 1350.11], [19492.60, 1137.87],
[17885.39, 1562.12], [17558.76, 3016.55]],
index = ['SHANGHAI', 'BEIJING ', 'GUANGZHOU', 'CHONGQING ', 'SUZHOU', 'CHENGDU'],
columns=['GDP', 'Population']
)
gp.index.name = 'City_Name'
gp.columns.name ='Items'
print(gp)
输出:
Items GDP Population
City_Name
SHANGHAI 27466.15 2419.70
BEIJING 24899.30 2172.90
GUANGZHOU 19610.90 1350.11
CHONGQING 19492.60 1137.87
SUZHOU 17885.39 1562.12
CHENGDU 17558.76 3016.55
data 参数所引用的值除上面的嵌套列表(该列表可以转换为二维数组)外, 还可以是字典 类型的数据。
import pandas as pd
gp = pd.DataFrame ({'city':['beijing', 'beijing', 'hubei', 'shanghai'],
'marks': [100, 96.91, 82.57, 82.47]},
index=['PKU', 'Tsinghua','WHU','Fudan'])
print(gp)
输出:
city marks
PKU beijing 100.00
Tsinghua beijing 96.91
WHU hubei 82.57
Fudan shanghai 82.47
用于创建 DataFrame 对象的数据,也包括自定义类型的数组
import numpy as np
import pandas as pd
u = np.array ([('beijing', 100),('beijing', 96.91), ('hubei', 82.57), ('shanghai', 82.47)],
dtype=[('city', '30S'),('marks', np.float)])
pg = pd.DataFrame(u, index=['PKU', 'Tsinghua', 'WHU', 'Fudan'])
print(pg)
输出:
city marks
PKU b'beijing' 100.00
Tsinghua b'beijing' 96.91
WHU b'hubei' 82.57
Fudan b'shanghai' 82.47
索引对象
在 Pandas 中,索引是对象,不仅可以有一级,还可以有多级。 也正是因为多级索引的存在, 才能够将本来多维的数据结构转换为二维或者一维,即 DataFrame 对象或者 Series 对象。
它们 的索引一-Index 对象和 Multilndex 对象。
Index 对象
每个 Series 对象都有一个 index 属性,通过此属 性得到的就是 Index 对象。
import numpy as np
import pandas as pd
s = pd.Series(np.random.randn(5))
print(s)
print(s.index)
print(s.index[0])
输出:
0 1.215105
1 -0.882641
2 -0.535513
3 0.104735
4 -1.186051
dtype: float64
RangeIndex(start=0, stop=5, step=1)
0
在创建 Series 对象的时候,我们己经通过 index 属性修改其“标签索引”的内容。
s.index = ['a', 'b', 'c', 'd', 'e']
print(s)
输出:
a 1.215105
b -0.882641
c -0.535513
d 0.104735
e -1.186051
dtype: float64
Python 中的对象都是通过类创建的,那 么 Index 对象能不能通过类创建呢?
pd.Index(data=None, dtype=None, copy=False, name=None, fastpath=False, tupleize_cols=True, **kwargs)
ind = pd.Index(['physics', 'python', 'math', 'english'])
s = pd.Series([100, 90, 80, 70], index=ind)
print(s)
输出:
physics 100
python 90
math 80
english 70
dtype: int64
Multilndex 对象
Pandas 里面提供了多种方法用于创建 Multilndex 对象,以及在 Series 对象和 DataFrame 对 象中应用它。
通过函数创建
通过实例化类创建
在数据中使用 MultiIndex 对象
import pandas as pd
gdp_index =[("shanghai", 2015), ('shanghai', 2016),
('beijing', 2015), ('beijing', 2016),
('guangzhou', 2015), ('guangzhou', 2016)]
gdp_mind = pd.MultiIndex.from_tuples(gdp_index)
gdp3 = pd.Series( [25300, 27466, 23000, 24899, 18100, 19611], index=gdp_mind)
print(gdp3)
输出:
shanghai 2015 25300
2016 27466
beijing 2015 23000
2016 24899
guangzhou 2015 18100
2016 19611
dtype: int64
在 Pandas 中,还有专门实现上述转换的函数,可以实现 Series 类型的对象和 DataFrame 类 型的对象之间的互换。
aa = gdp3.unstack()
print(aa)
print('********')
bb = aa.stack()
print(bb)
输出:
2015 2016
beijing 23000 24899
guangzhou 18100 19611
shanghai 25300 27466
*****************************
beijing 2015 23000
2016 24899
guangzhou 2015 18100
2016 19611
shanghai 2015 25300
2016 27466
dtype: int64
数据索引和切片
Series 对象索引和切片的使用
import pandas as pd
g = np.array([27466.15, 24899.3, 19610.9, 19492.4])
gdp = pd.Series(g, index=['shanghai','beijing', 'guangzhou', 'shenzhen'])
print(gdp)
print('**********************')
#获取某一个索引的值
print(gdp['shanghai'])
#判断索引是否在数组中
print('shanghai' in gdp)
print('shanghai11' in gdp)
#获取所有的索引
print(gdp.keys())
#获取所有的索引和值
print(list(gdp.items()))
gdp['hangzhou'] = 11050.5 #增加一项
print('******************************')
#同时获取多个索引的值
print(gdp[['shanghai','beijing']])
print('*********')
print(gdp[gdp>20000])
# 对于 Series 对象,拥有了标签索引的同时,位置索引也没有失效,所以依然可以通过位置 索引获取元素,跟 NumPy 中的数组一样。
print('-----------------------')
print(gdp[2])
print('-----------------------')
print(gdp[2:5])
输出;
shanghai 27466.15
beijing 24899.30
guangzhou 19610.90
shenzhen 19492.40
dtype: float64
**********************
27466.15
True
False
Index(['shanghai', 'beijing', 'guangzhou', 'shenzhen'], dtype='object')
[('shanghai', 27466.15), ('beijing', 24899.3), ('guangzhou', 19610.9), ('shenzhen', 19492.4)]
******************************
shanghai 27466.15
beijing 24899.30
dtype: float64
*********
shanghai 27466.15
beijing 24899.30
dtype: float64
-----------------------
19610.9
-----------------------
guangzhou 19610.9
shenzhen 19492.4
hangzhou 11050.5
dtype: float64
当索引为整数的时候,标签索引和位置索引会引起混乱,所以:
-
若使用位置索引读取某些值,提倡使用 series.iloc[ ]。
-
若使用标签索引读取某些值,提倡使用 series.loc[ ]。
s = pd.Series(np.random.randn(4), index=[1, 3, 5, 7])
print(s)
print('***********')
#位置索引
print(s.iloc[1])
print('-------')
print(s.iloc[1:3])
print('*********')
#标签索引
print(s.loc[1])
print(s.loc[1:3])
输出:
1 0.700621
3 -1.900641
5 -0.584151
7 0.413870
dtype: float64
***********
-1.9006412182989636
-------
3 -1.900641
5 -0.584151
dtype: float64
*********
0.7006208932997835
1 0.700621
3 -1.900641
dtype: float64
import pandas as pd
gdp_index = [('shanghai', 2015), ('shanghai', 2016), ('beijing', 2015), ('beijing', 2016), ('guangzhou', 2015),
('guangzhou', 2016)]
gdp_mind = pd.MultiIndex.from_tuples(gdp_index)
gdp = pd.Series([25300, 27466, 23000, 24899, 18100, 19611], index=gdp_mind)
print('''*******gdp***********''')
print(gdp)
print('''*******gdp['shanghai']***********''')
print(gdp['shanghai'])
#标签索引
print('''*******gdp.loc['shanghai']***********''')
print(gdp.loc['shanghai'])
print('''*******gdp.loc['shanghai', 2016]***********''')
print(gdp.loc['shanghai', 2016])
print('''*******gdp.loc[:,2015]***********''')
print(gdp.loc[:,2015])
#位置索引
print('''*******gdp.iloc[1]***********''')
print(gdp.iloc[1])
print('''*******gdp.iloc[1:5]***********''')
print(gdp.iloc[1:5])
print('''*******gdp.iloc[[1, 3, 5]]***********''')
print(gdp.iloc[[1, 3, 5]])
输出:
*******gdp***********
shanghai 2015 25300
2016 27466
beijing 2015 23000
2016 24899
guangzhou 2015 18100
2016 19611
dtype: int64
*******gdp['shanghai']***********
2015 25300
2016 27466
dtype: int64
*******gdp.loc['shanghai']***********
2015 25300
2016 27466
dtype: int64
*******gdp.loc['shanghai', 2016]***********
27466
*******gdp.loc[:,2015]***********
shanghai 25300
beijing 23000
guangzhou 18100
dtype: int64
*******gdp.iloc[1]***********
27466
*******gdp.iloc[1:5]***********
shanghai 2016 27466
beijing 2015 23000
2016 24899
guangzhou 2015 18100
dtype: int64
*******gdp.iloc[[1, 3, 5]]***********
shanghai 2016 27466
beijing 2016 24899
guangzhou 2016 19611
dtype: int64
.iloc[]和 loc[]分别提供了两个途径,允许在索引上分别使用位置索引和标签索引,为我们 从 Series 对象中取值提供了多种途.
DataFrame 对象
DataFrame 是二维的 Pandas 数据, 可以在一定程度上类比二维数组.
import pandas as pd
population = pd. Series ([2415.27, 2151.6, 1270.08], index= ['shanghai','beijing', 'guangzhou'])
gdp =pd .Series( [27466, 24899, 19611], index=['shanghai','beijing','guangzhou'])
d = pd.DataFrame ({'gdp':gdp, 'pop':population})
print('''---------d-------------''')
print(d)
#DataFrame 对象是类二维数组,其实撇开索引,其元素就是一个二维数组。
print('''---------d.values-------------''')
print(d.values)
# 如果仅取某列数据,则可以根据列名称或者宇段名称直接获得。
print('''-------------d['pop']-------------------''')
print(d['pop'])
#如果要获得某些行的切片,则可以用下边多种方式,
print('''---------------d['shanghai':'beijing']---------------------''')
print(d['shanghai':'beijing'])
print('''--------------d.loc['shanghai':'beijing']--------------------''')
print(d.loc['shanghai':'beijing'])
print('''-------------d.iloc[1:]------------------''')
print(d.iloc[1:])
#灵活获取
print('''--------d.loc['shanghai', 'pop']----------''')
print(d.loc['shanghai', 'pop'])
print('''--------d.loc[:, 'pop']----------''')
print(d.loc[:, 'pop'])
输出:
---------d-------------
gdp pop
shanghai 27466 2415.27
beijing 24899 2151.60
guangzhou 19611 1270.08
---------d.values-------------
[[27466. 2415.27]
[24899. 2151.6 ]
[19611. 1270.08]]
-------------d['pop']-------------------
shanghai 2415.27
beijing 2151.60
guangzhou 1270.08
Name: pop, dtype: float64
---------------d['shanghai':'beijing']---------------------
gdp pop
shanghai 27466 2415.27
beijing 24899 2151.60
--------------d.loc['shanghai':'beijing']--------------------
gdp pop
shanghai 27466 2415.27
beijing 24899 2151.60
-------------d.iloc[1:]------------------
gdp pop
beijing 24899 2151.60
guangzhou 19611 1270.08
--------d.loc['shanghai', 'pop']----------
2415.27
--------d.loc[:, 'pop']----------
shanghai 2415.27
beijing 2151.60
guangzhou 1270.08
Name: pop, dtype: float64
文件读取与存储
pandas提供了⼀些⽤于将表格型数据读取为DataFrame对象的函数。其中read_csv和read_table可能会是你今后⽤得最多的。
csv操作 pandas.read_csv和pandas.read_table
读取csv
read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False,keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='"', quoting=0,escapechar=None, comment=None, encoding=None, dialect=None, tupleize_cols=None,error_bad_lines=True, warn_bad_lines=True, skipfooter=0, doublequote=True, delim_whitespace=False,low_memory=True, memory_map=False, float_precision=None)
read_table(...)
- filepath_or_buffer:文件路径
- sep 指定分隔符。如果不指定参数,则会尝试使用逗号分隔。
- header 指定行数用来作为列名,数据开始行数。如果文件中没有列名,则默认为0,否则设置为None。
- usecols:指定读取的列名,列表形式,用作筛选所需要的数据,也可以通过drop函数剔除数据
- names:如果遇到直接就是数据的文件,需要通过names参数手动填入索引项
- skipinitialspace 忽略分隔符后的空白
- skiprows 需要忽略的行数(从文件开始处算起),或需要跳过的行号列表(从0开始)
- nrows 需要读取的行数(从文件头开始算起)。
实例:
读取有标题的文件
#ex1.csv 文件内容
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
import pandas as pd
import numpy as np
df = pd.read_csv('./ex1.csv')
print(df)
print('''-----df.keys()---------''')
print(df.keys())
输出:
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
-----df.keys()---------
Index(['a', 'b', 'c', 'd', 'message'], dtype='object')
还可以使⽤read_table,并指定分隔符
import pandas as pd
import numpy as np
df = pd.read_table('./ex1.csv',sep=',')
print(df)
输出:
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
读取没有标题的文件:
#文件内容
ex1.csv
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
#让pandas为其分配默认的列名
df = pd.read_csv('./ex1.csv', header=None)
print(df)
输出:
0 1 2 3 4
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
#⾃⼰定义列名
names = ['a', 'b', 'c', 'd', 'message']
df = pd.read_csv('./ex1.csv', names=names)
print(df)
输出:
0 1 2 3 4
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
假设你希望将message列做成DataFrame的索引。你可以明确表 示要将该列放到索引4的位置上,也可以通过index_col参数指 定"message":
names = ['a', 'b', 'c', 'd', 'message']
df = pd.read_csv('./ex1.csv', names=names,index_col=names[4])
print(df)
输出:
a b c d
message
hello 1 2 3 4
world 5 6 7 8
foo 9 10 11 12
如果希望将多个列做成⼀个层次化索引,只需传⼊由列编号或列 名组成的列表即可
#文件内容
key1,key2,value1,value2
one,a,1,2
one,b,3,4
one,c,5,6
one,d,7,8
two,a,9,10
two,b,11,12
two,c,13,14
two,d,15,16
df = pd.read_csv('./ex1.csv', index_col=['key1', 'key2'])
print(df)
输出:
value1 value2
key1 key2
one a 1 2
b 3 4
c 5 6
d 7 8
two a 9 10
b 11 12
c 13 14
d 15 16
⽤skiprows跳过⽂件的指定⾏
# hey!
a,b,c,d,message
# just wanted to make things more difficult for you
# who reads CSV files with computers, anyway?
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
df = pd.read_csv('./ex1.csv', skiprows=[0, 2, 3])
print(df)
输出:
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
逐块读取⽂本⽂件
在处理很⼤的⽂件时,或找出⼤⽂件中的参数集以便于后续处理时,你可能只想读取⽂件的⼀⼩部分或逐块对⽂件进⾏迭代。
如果只想读取⼏⾏(避免读取整个⽂件),通过nrows进⾏指定即可:
df = pd.read_csv('./ex1.csv', nrows=2)
print(df)
输出:#输出0 ,1 行
1 2 3 4 hello
0 5 6 7 8 world
1 9 10 11 12 foo
处理分隔符格式
⼤部分存储在磁盘上的表格型数据都能⽤pandas.read_table进⾏加载。然⽽,有时还是需要做⼀些⼿⼯处理。由于接收到含有畸形⾏的⽂件⽽使read_table出⽑病的情况并不少⻅
-
对于任何单字符分隔符⽂件,可以直接使⽤Python内置的csv模块。将任意已打开的⽂件或⽂件型的对象传给csv.reader
-
对这个reader进⾏迭代将会为每⾏产⽣⼀个元组(并移除了所有的引号)
-
CSV⽂件的形式有很多。只需定义csv.Dialect的⼀个⼦类即可定义出新格式(如专⻔的分隔符、字符串引⽤约定、⾏结束符等):
import csv
f = open('./ex1.csv')
reader = csv.reader(f, delimiter=',')
for line in reader:
print(line)
输出:
['1', '2', '3', '4', 'hello']
['5', '6', '7', '8', 'world']
['9', '10', '11', '12', 'foo']
['1', '2', '3', '4', 'hello']
['5', '6', '7', '8', 'world']
['9', '10', '11', '12', 'foo']
写入csv
DataFrame.to_csv(path_or_buf=None, sep=',', columns=None, header=True, index=True, index_label=None,mode='w', encoding=None)
- path_or_buf:文件路径
- sep:分隔符
- columns:要保存的列,列表形式
- header:默认为True,是否写进列索引值
- index:是否写进行索引值
- mode:w为重写,a为追加
- series和dataframe操作基本一致
HDF5操作
HDF5的存储支持压缩,使用的方式是blosc,速度最快也是pandas默认支持的,可以提高磁盘利用率,节省空间的同时还支持跨平台,可以轻松迁移到hadoop上面,HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame,一个键对应一个DataFrame,也可以相当于是存储三维数据了
读取hdf5
读取以及写入需要指定键,不同的键对应不同的DataFrame
pandas.read_hdf(path_or_buf, key=None, **kwargs)
- key:读取的键
- mode:打开文件的方式
写入hdf5文件
可以写入同一个hdf5文件当中,以不同的键区分开来
DataFrame.to_hdf(path_or_buf, key, kwargs)
JSON文件操作
读取
pandas.read_json(path_or_buf=None,orient=None,typ='frame',lines=False)
- orient:指定格式,以下为参数值
- split
- records(最常用的格式,其他了解即可)
- index
- columns
- values
- lines:是否逐行读取,默认为False
- typ:指定转换成的对象类型,series或者dataframe,默认为frame
写入
pandas.to_json(path_or_buf=None,orient=None,typ='frame',lines=False)
处理缺失数据
NumPy 中的缺失数据
a= np.array([1, None, 5, 7, 9])
b = np.array([1, 3, 5, 7, 9])
#因为 a 中有一个 None,所以对该数组元素类型进行判断的时候,
# 返回的是 objecto 如果对 数组 a 进行运算,肯定是要报锚的。
print(a.dtype)
print(b.dtype)
输出:
object
int32
NumPy 提供了另外一个表示空缺的数据 np.nan,才能够像一个数字那样参与各种运算。
c = np.array([1, np.nan, 5, 7, 9])
print(c.dtype)
print(7 + np.nan)
print(0 * np.nan)
print(c.sum())
print(np.nansum(c))
print(np.nanmean(c))
输出:
object
int32
float64
nan
nan
nan
22.0
5.5
Pandas 处理缺失数据
s = pd.Series([1, np.nan, 3, None, 7, 9])
print(s)
输出:
0 1.0
1 NaN
2 3.0
3 NaN
4 7.0
5 9.0
dtype: float64
尽管在创建 Series 对象的列表中有 None,但在最终的 Series 中却被转换为 NaN,这样就不 妨碍计算了,并且在计算时, Pandas 自动摒除了 NaN 数据。
import pandas as pd
import numpy as np
s = pd.Series([1, np.nan, 3, None, 7, 9])
print(s)
#求和
print('-------s.sum()----------')
print(s.sum())
#判断是否空
print('---------s.isnull()----------')
print(s.isnull())
print('----------s.notnull()-----------')
print(s.notnull())
#获取非空数据
print('-------s[s.notnull()]----------')
print(s[s.notnull()])
#删除所有 NaN 数据,并返回不含 NaN 的新对象
print('---------s.dropna()---------')
print(s.dropna())
输出:
0 1.0
1 NaN
2 3.0
3 NaN
4 7.0
5 9.0
dtype: float64
-------s.sum()----------
20.0
---------s.isnull()----------
0 False
1 True
2 False
3 True
4 False
5 False
dtype: bool
----------s.notnull()-----------
0 True
1 False
2 True
3 False
4 True
5 True
dtype: bool
-------s[s.notnull()]----------
0 1.0
2 3.0
4 7.0
5 9.0
dtype: float64
---------s.dropna()---------
0 1.0
2 3.0
4 7.0
5 9.0
dtype: float64
dropna()的作用是删除所有 NaN 数据,并返回不含 NaN 的新对象, 注意原有的对象没有受 到影响。对于 Series 对象比较好理解,如果是 DataFrame 对象, 应该怎样 “删除” 呢?是删除 行, 还是删除列?
df = pd.DataFrame([[1, 2, np.nan, 4], [5, None, 7, 8], [9, 10, 11, 12]])
print(df)
#dropna()的作用是删除所有 NaN 数据,并返回不含 NaN 的新对象
print('----------df.dropna()-----------------')
print(df.dropna())
print('-----------df.dropna(axis=l)--------------')
print(df.dropna(axis=1))
print('''---------df.dropna(axis= 'columns')-----------''')
print(df.dropna(axis= 'columns'))
#fillna()的作用是用某个值把数据中的 NaN 替换掉
print('''--------df.fillna(method='ffill')------------''')
print(df.fillna(method='ffill')) # 根据前面的值替换 NaN
print('''--------df.fillna(method='bfill')----------''')
print(df.fillna(method='bfill')) ##根据后面的位替换 NaN
print('''------------df.fillna(method='ffill', axis=1)------------''')
print(df.fillna(method='ffill', axis=1))
输出:
0 1 2 3
0 1 2.0 NaN 4
1 5 NaN 7.0 8
2 9 10.0 11.0 12
----------df.dropna()-----------------
0 1 2 3
2 9 10.0 11.0 12
-----------df.dropna(axis=l)--------------
0 3
0 1 4
1 5 8
2 9 12
---------df.dropna(axis= 'columns')-----------
0 3
0 1 4
1 5 8
2 9 12
--------df.fillna(method='ffill')------------
0 1 2 3
0 1 2.0 NaN 4
1 5 2.0 7.0 8
2 9 10.0 11.0 12
--------df.fillna(method='bfill')----------
0 1 2 3
0 1 2.0 7.0 4
1 5 10.0 7.0 8
2 9 10.0 11.0 12
------------df.fillna(method='ffill', axis=1)------------
0 1 2 3
0 1.0 2.0 2.0 4.0
1 5.0 5.0 7.0 8.0
2 9.0 10.0 11.0 12.0
规整数据
轴向连接
在 NumPy 中,有一个名为 np.concatenate()的函数, 这个函数通过对 axis 参数进行赋值,实 现沿着所设置的轴方向连接数组。 Pandas 也提供了一个类似的函数,不过其参数更丰富。
pd.concat(objs, axis=0, join=’outer ’, join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
-
objs 参与连接的对象,是必需的, 不能省略(序列或 Series DataFrame、 Panel 、字典等对象 )
-
axis 指定沿着哪个轴的方向连接 (0或 1 默认为 0)
-
join 默认为 outero 其他轴上的索引是按照 outer (并集)还是 inner (交集)连接
-
join_axes 指定其他 n-1 条轴索引 , 不执行交集/并集操作。 比如对于 DataFrame 对象,当 axis=0 时, 若 join axes 是列表,则该列表的值就是 DataFrame 的列标签
-
ignore_index 默认为 False。如果为 True,就摒弃连接铀的索引,代之以 0, ., n 一 l 的整数,这是一种新的索引
-
keys 默认为 Noneo 用于设置多级索引
-
levels 默认为 None 指定用于多级索引的标签
-
names 默认为 None。多级索引的名称
-
verify _integrity 默认为 False。 如果为 True, 当检查到连接的轴有重复时,会发起异常
连接两个 Series 对象,其他参数都采用默认值, 默认连接方向是 0 轴方向
sl = pd.Series( [100, 200, 300], index=['a', 'b', 'c'])
s2 = pd.Series ([400, 500, 600], index=['d', 'e', 'f'])
print(pd.concat([sl, s2]))
输出:
a 100
b 200
c 300
d 400
e 500
f 600
dtype: int64
连接对象是 DataFrame 对象
df1 = pd.DataFrame([[110, 120, 130],[210, 220, 230], [310, 320, 330]])
df2 = pd.DataFrame([[11, 12, 13],[21, 22, 23], [31, 32, 33]])
print(pd.concat([df1, df2]))
输出:
0 1 2
0 110 120 130
1 210 220 230
2 310 320 330
0 11 12 13
1 21 22 23
2 31 32 33
对象的结构不同
sl = pd.Series([100, 200, 300], index=['a', 'b', 'c'])
df1 = pd.DataFrame([[110, 120, 130],[210, 220, 230], [310, 320, 330]])
print(pd.concat([df1, sl]))
输出:
0 1 2
0 110 120.0 130.0
1 210 220.0 230.0
2 310 320.0 330.0
a 100 NaN NaN
b 200 NaN NaN
c 300 NaN NaN
sl = pd.Series([100, 200, 300], index=['a', 'b', 'c'])
df1 = pd.DataFrame([[110, 120, 130],[210, 220, 230], [310, 320, 330]])
print(pd.concat([df1, sl], keys=['df1', 's1']))
输出:
0 1 2
df1 0 110 120.0 130.0
1 210 220.0 230.0
2 310 320.0 330.0
s1 a 100 NaN NaN
b 200 NaN NaN
c 300 NaN NaN
要实现沿着1轴方向连接,设定参数 axis=1即可
df1 = pd.DataFrame([[110, 120, 130],[210, 220, 230], [310, 320, 330]])
df2 = pd.DataFrame([[11, 12, 13],[21, 22, 23], [31, 32, 33]])
print(pd.concat([df1, df2], axis=1))
输出:
0 1 2 0 1 2
0 110 120 130 11 12 13
1 210 220 230 21 22 23
2 310 320 330 31 32 33
df1 = pd.DataFrame([[110, 120, 130],[210, 220, 230], [310, 320, 330]], index=['a', 'c', 'd'])
df2 = pd.DataFrame([[11, 12, 13],[21, 22, 23], [31, 32, 33]], index=['b', 'c', 'd'])
print('''-------pd.concat([df1, df2], axis=1, join='outer')----------''')
print(pd.concat([df1, df2], axis=1, join='outer'))
print('''----pd.concat([df1, df2], axis=1, join='inner')-----''')
print(pd.concat([df1, df2], axis=1, join='inner'))
输出:
-------pd.concat([df1, df2], axis=1, join='outer')----------
0 1 2 0 1 2
a 110.0 120.0 130.0 NaN NaN NaN
c 210.0 220.0 230.0 21.0 22.0 23.0
d 310.0 320.0 330.0 31.0 32.0 33.0
b NaN NaN NaN 11.0 12.0 13.0
----pd.concat([df1, df2], axis=1, join='inner')-----
0 1 2 0 1 2
c 210 220 230 21 22 23
d 310 320 330 31 32 33
合并数据
pd.merge()此函数是针对 DataFrame 对象而言的,并且对其实 施的是“database-style join”(数据库风格合并)
pd.merge(left,right, how=’ inner ’, on=None, left_on=None ,right_on=None, left_index=False right_index=False, sort=False, suffixes=(’_x', '_y ' ), copy=True, indicator=False)
- left/right Data Frame 进行合并的两个 DataFrame 对象
- how 默认为’inner’。
- left/right: 仅以 left/right 的 DataFrame 对象中所指定的列为健、以并集 (outer)的方式合并数据。
- outer: 两个 DataFrame 对象指定键的并集
- inner: 两个 DataFrame 对象指定键的交集
- on 默认为 Noneo 用于合并的字段名称(列标签)。一般是两个 DaraFrame 所共的列,如果on=None, 且未指定合并的链,则以两个 DataFrame 对象列标签的交集为合并的键
- left_ on/right_ on 默认为 None。 从 left/right 所引用的DataFrame 对象中选择记录(列标签)作为数据合并的键
- left_index/light_index 默认为 False。 如果为 True,则以 left/right 所引用对象的索引为建合并数据
left_df = pd.DataFrame({'grade':['a','b', 'b', 'a', 'c' ,'c', 'd' ], 'ldata': range(7)})
right_df = pd.DataFrame({'grade':['a', 'b', 'c'], 'rdata': [30, 40, 50]})
print(left_df)
print(right_df)
print('''-----pd.merge(left_df,right_df)-----''')
print(pd.merge(left_df,right_df))
print('''-----pd.merge(left_df, right_df, on='grade', how='inner')----''')
print(pd.merge(left_df, right_df, on='grade', how='inner'))
输出:
grade ldata
0 a 0
1 b 1
2 b 2
3 a 3
4 c 4
5 c 5
6 d 6
grade rdata
0 a 30
1 b 40
2 c 50
-----pd.merge(left_df,right_df)-----
grade ldata rdata
0 a 0 30
1 a 3 30
2 b 1 40
3 b 2 40
4 c 4 50
5 c 5 50
-----pd.merge(left_df, right_df, on='grade', how='inner')----
grade ldata rdata
0 a 0 30
1 a 3 30
2 b 1 40
3 b 2 40
4 c 4 50
5 c 5 50
能够被指定为键的列也可 以是多个
ldf = pd.DataFrame({'keyl': ['K0', 'K0', 'Kl', 'K2'], 'key2': ['K0', 'Kl', 'K0', 'Kl'],
'A':['A0', 'Al', 'A2','A3'], 'B':['B0','Bl','B3', 'B3']})
rdf = pd.DataFrame({'keyl':['K0', 'Kl','Kl','K2'], 'key2': ['K0', 'K0', 'K0', 'K0'],
'C':['C0', 'C1','C2','C3'], 'D':['D0', 'Dl', 'D2','D3']})
print(ldf)
print(rdf)
print('''--pd.merge(ldf,rdf, on=['keyl', 'key2'], how='inner')---''')
print(pd.merge(ldf, rdf, on=['keyl', 'key2'], how='inner'))
print('''--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='outer')---''')
print(pd.merge(ldf, rdf, on=['keyl', 'key2'], how='outer'))
print('''--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left')----''')
print(pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left'))
print('''--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left', indicator=True)---''')
print(pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left', indicator=True))
输出:
keyl key2 A B
0 K0 K0 A0 B0
1 K0 Kl Al Bl
2 Kl K0 A2 B3
3 K2 Kl A3 B3
keyl key2 C D
0 K0 K0 C0 D0
1 Kl K0 C1 Dl
2 Kl K0 C2 D2
3 K2 K0 C3 D3
--pd.merge(ldf,rdf, on=['keyl', 'key2'], how='inner')---
keyl key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 Kl K0 A2 B3 C1 Dl
2 Kl K0 A2 B3 C2 D2
--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='outer')---
keyl key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 Kl Al Bl NaN NaN
2 Kl K0 A2 B3 C1 Dl
3 Kl K0 A2 B3 C2 D2
4 K2 Kl A3 B3 NaN NaN
5 K2 K0 NaN NaN C3 D3
--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left')----
keyl key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 Kl Al Bl NaN NaN
2 Kl K0 A2 B3 C1 Dl
3 Kl K0 A2 B3 C2 D2
4 K2 Kl A3 B3 NaN NaN
--pd.merge(ldf, rdf, on=['keyl', 'key2'], how='left', indicator=True)---
keyl key2 A B C D _merge
0 K0 K0 A0 B0 C0 D0 both
1 K0 Kl Al Bl NaN NaN left_only
2 Kl K0 A2 B3 C1 Dl both
3 Kl K0 A2 B3 C2 D2 both
4 K2 Kl A3 B3 NaN NaN left_only
组合数据
np.where()函数,根据条件对 a 和 b 中的数据元素进行筛选, 最终得到根据 条件选择出来的新的数据一一这个数据不是合井和连接而成的,而是分别从 a 和 b 中取出部分 若干元素新生成的 Series 对象
a = pd.Series([np.nan, 2, 4, np.nan, 8, 10])
b = pd.Series([1, 2, np.nan, np.nan, 5, np.nan])
print('''--np.where(pd.isnull(b), a, b)---''')
print(np.where(pd.isnull(b), a, b))
print('''---b.combine_first(a)--''')
print(b.combine_first(a))
输出:
--np.where(pd.isnull(b), a, b)---
[ 1. 2. 4. nan 5. 10.]
---b.combine_first(a)--
0 1.0
1 2.0
2 4.0
3 NaN
4 5.0
5 10.0
dtype: float64
DataFrame 类的实例对象也有 combine_first()方法。
dfl = pd.DataFrame({'one':[11, 12, np.nan, 13, np.nan],'two':[np.nan, 22, 23, np.nan, 24]})
df2 = pd.DataFrame({'one':np.arange(6),'two':np.linspace(10, 100, 6), 'three': np.logspace(2, 3, 6)})
print(dfl)
print(df2)
print('''---dfl.combine_first(df2)----''')
#使用df2补充df1中的数据
print(dfl.combine_first(df2))
输出:
one two
0 11.0 NaN
1 12.0 22.0
2 NaN 23.0
3 13.0 NaN
4 NaN 24.0
one two three
0 0 10.0 100.000000
1 1 28.0 158.489319
2 2 46.0 251.188643
3 3 64.0 398.107171
4 4 82.0 630.957344
5 5 100.0 1000.000000
---dfl.combine_first(df2)----
one three two
0 11.0 100.000000 10.0
1 12.0 158.489319 22.0
2 2.0 251.188643 23.0
3 13.0 398.107171 64.0
4 4.0 630.957344 24.0
5 5.0 1000.000000 100.0
数据转换
行列转换
data= pd.DataFrame(np.arange(10).reshape(2, 5), index=['one', 'two'] , columns= ['a', 'b', 'c', 'd', 'e'])
print(data)
print('''---data.stack()----''')
print(data.stack())
print('''---data.stack().unstack()---''')
print(data.stack().unstack())
输出:
a b c d e
one 0 1 2 3 4
two 5 6 7 8 9
---data.stack()----
one a 0
b 1
c 2
d 3
e 4
two a 5
b 6
c 7
d 8
e 9
dtype: int32
---data.stack().unstack()---
a b c d e
one 0 1 2 3 4
two 5 6 7 8 9
透视表
在电子表格中,有一种叫做“透视表”的操作,可以根据数据再归类。在 Pandas 里面,也有一个“透视表”的函数,用来实现此功能。
students= pd.DataFrame({'class':['classl' , 'class2', 'classl' , 'class2' ],
'subject':['physics','python','math ','physics'],
'numbers': [ 28, 30, 20, 80]})
print(students)
print('''--------------------''')
print(students.pivot(index= 'class', columns='subject', values='numbers'))
输出:
class subject numbers
0 classl physics 28
1 class2 python 30
2 classl math 20
3 class2 physics 80
--------------------
subject math physics python
class
class2 NaN 80.0 30.0
classl 20.0 28.0 NaN
分组运算
简单的统计运算
dfl = pd.DataFrame({'one':[11, 12, 14, 13, 15],'two':[11, 22, 23, 12, 24]})
print(dfl)
print('''----dfl.sum()-----''')
#求和
print(dfl.sum())
print('''----dfl.mean()----''')
#平均值
print(dfl.mean())
print(dfl.mean(axis=1))
#中位数
print('''---dfl.median()----''')
print(dfl.median())
print('''dfl.describe()''')
print(dfl.describe())
输出:
one two
0 11 11
1 12 22
2 14 23
3 13 12
4 15 24
----dfl.sum()-----
one 65
two 92
dtype: int64
----dfl.mean()----
one 13.0
two 18.4
dtype: float64
0 11.0
1 17.0
2 18.5
3 12.5
4 19.5
dtype: float64
---dfl.median()----
one 13.0
two 22.0
dtype: float64
dfl.describe()
one two
count 5.000000 5.000000
mean 13.000000 18.400000
std 1.581139 6.348228
min 11.000000 11.000000
25% 12.000000 12.000000
50% 13.000000 22.000000
75% 14.000000 23.000000
max 15.000000 24.000000
分组运算
为了理解分组,还是先完整呈现 groupby()方法的参数列表。
df .groupby(by=None, axis=0, level=None, as_index=True, soue=True, goup_keys=True, squeeze=False, **kwargs)
其中,参数 by 用来指明为当前数据对象进行分组的依据, 即分组的键。能够作为键的数据 类型包括字符串和其他可法代对象、函数或其他表达对应关系的对象类型。
df = pd.DataFrame({'subject':['math', 'physics', 'english', 'math', 'physics', 'english'],
'score':[90, 80, 70, 95 , 85, 75]})
print(df)
print('''----df.groupby("subject").sum()---''')
print(df.groupby("subject").sum())
输出:
subject score
0 math 90
1 physics 80
2 english 70
3 math 95
4 physics 85
5 english 75
----df.groupby("subject").sum()---
score
subject
english 145
math 185
physics 165
分组对象的运算方法
import pandas as pd
df = pd.DataFrame({'subject':['math', 'physics', 'english', 'math', 'physics', 'english'],
'score':[90, 80, 70, 95 , 85, 75]})
df ['teacher'] = [ 'Netwon', 'Netwon', 'Pascal', 'Netwon', 'Pascal' , 'Pascal']
df ['rank'] = [4, 5, 2, 9, 7, 5]
print(df)
print (df.groupby('teacher')['score'].describe())
输出:
score subject teacher rank
0 90 math Netwon 4
1 80 physics Netwon 5
2 70 english Pascal 2
3 95 math Netwon 9
4 85 physics Pascal 7
5 75 english Pascal 5
count mean std min 25% 50% 75% max
teacher
Netwon 3.0 88.333333 7.637626 80.0 85.0 90.0 92.5 95.0
Pascal 3.0 76.666667 7.637626 70.0 72.5 75.0 80.0 85.0
Panda 为分组对象提供了 些专有方法, aggregate ()、 apply()、filter()、 transform (), 用于解决分组运算中个性化的计算要求。注意 它们都是分组对象的方法 即它们都以分组 对象为单位进行计 ,
aggregate () 函数的 作用是可以将若干个用于统计运算 函数聚合 一起。
df = pd.DataFrame({'subject':['math', 'physics', 'english', 'math', 'physics', 'english'],
'score':[90, 80, 70, 95 , 85, 75]})
df ['teacher'] = [ 'Netwon', 'Netwon', 'Pascal', 'Netwon', 'Pascal' , 'Pascal']
df ['rank'] = [4, 5, 2, 9, 7, 5]
print(df)
print ('''-----df.groupby('teacher')['score'].describe()------''')
print (df.groupby('teacher')['score'].describe())
print ('''----df.groupby ('teacher') .aggregate(['mean', 'std', 'max'])------''')
print (df.groupby ('teacher') .aggregate(['mean', 'std', 'max']))
#,如果 aggregate ()的 参数不是由多个函数对象组成的列 ,而是一个函数对象,那么
# 就与下面所示一样了。
print ('''---df.groupby ('teacher').aggregate(np.median)----''')
print (df.groupby ('teacher').aggregate(np.median))
#aggregate () 方法还能够对不同 的列进行不 同的运算,方法就是 典形式建立
# 列标签 函数对象的映射关系
print ('''---df.groupby('teacher').aggregate({'score':np.mean, 'rank':np.median})---''')
print (df.groupby('teacher').aggregate({'score':np.mean, 'rank':np.median}))
输出:
score subject teacher rank
0 90 math Netwon 4
1 80 physics Netwon 5
2 70 english Pascal 2
3 95 math Netwon 9
4 85 physics Pascal 7
5 75 english Pascal 5
-----df.groupby('teacher')['score'].describe()------
count mean std min 25% 50% 75% max
teacher
Netwon 3.0 88.333333 7.637626 80.0 85.0 90.0 92.5 95.0
Pascal 3.0 76.666667 7.637626 70.0 72.5 75.0 80.0 85.0
----df.groupby ('teacher') .aggregate(['mean', 'std', 'max'])------
score rank
mean std max mean std max
teacher
Netwon 88.333333 7.637626 95 6.000000 2.645751 9
Pascal 76.666667 7.637626 85 4.666667 2.516611 7
---df.groupby ('teacher').aggregate(np.median)----
score rank
teacher
Netwon 90 5
Pascal 75 5
---df.groupby('teacher').aggregate({'score':np.mean, 'rank':np.median})---
score rank
teacher
Netwon 88.333333 5
Pascal 76.666667 5
filter() 筛选数据
df = pd.DataFrame({'subject':['math', 'physics', 'english', 'math', 'physics', 'english'],
'score':[90, 80, 70, 95 , 85, 75]})
df ['teacher'] = [ 'Netwon', 'Netwon', 'Pascal', 'Netwon', 'Pascal' , 'Pascal']
df ['rank'] = [4, 5, 2, 9, 7, 5]
print(df)
print (df.groupby('subject').filter(lambda x: x['rank'].mean() > 5))
输出:
score subject teacher rank
0 90 math Netwon 4
1 80 physics Netwon 5
2 70 english Pascal 2
3 95 math Netwon 9
4 85 physics Pascal 7
5 75 english Pascal 5
score subject teacher rank
0 90 math Netwon 4
1 80 physics Netwon 5
3 95 math Netwon 9
4 85 physics Pascal 7
transform()
print (df.groupby('subject').transform(lambda x: x - x. mean()))
输出:
score rank
0 -2.5 -2.5
1 -2.5 -1.0
2 -2.5 -1.5
3 2.5 2.5
4 2.5 1.0
5 2.5 1.5
apply()
相对于前述的分组对象的各个方法,apply()比它们更灵活。
def rank_score(x): #创建一个函数
x['rank_score'] = x['score'] * x['rank'].std()
return x
print (df_subject.apply(rank_score))
输出:
score subject teacher rank rank_score
0 90 math Netwon 4 318.198052
1 80 physics Netwon 5 113.137085
2 70 english Pascal 2 148.492424
3 95 math Netwon 9 335.875721
4 85 physics Pascal 7 120.208153
5 75 english Pascal 5 159.099026
来源:oschina
链接:https://my.oschina.net/u/3696975/blog/3165324