《利用python进行数据分析》学习笔记--pandas(1)
pandas主要的两个数据结构是:Series 和DataFrame
1、Series
series 类似于一维数组,由 索引+数据组成
若不指定索引,则会自动创建0到N-1的整数型索引,
可以用series的values获取数组值,用index获取索引值。
import pandas as pd obj = pd.Series ([3,6,9,7],index = ['c','b','d','a']) obj 返回为 c 3 b 6 d 9 a 7 dtype: int64 此时可以通过索引选取值 obj['d'] 返回为 9
Numpy的数组运算(布尔型数组过滤、标量乘、数学函数)不会改变索引和值之间的链接
obj * 3 c 9 b 18 d 27 a 21 dtype: int64 np.exp(obj) c 20.085537 b 403.428793 d 8103.083928 a 1096.633158 dtype: float64
如果数据存放在一个Python字典中,可以通过字典来创建Series
data = {'JiangSu':20000,'JiangXi':35000,'FuJian':15000,'GuangDong':40000} obj = pd.Series(data) obj 返回为 JiangSu 20000 JiangXi 35000 FuJian 15000 GuangDong 40000 dtype: int64
如果只传如一个字典,则Series的索引就是原字典的键。
states = ['FuJian','JiangSu','ZheJiang'] obj1 = pd.Series(data,index = states) obj1 返回为 FuJian 15000.0 JiangSu 20000.0 ZheJiang NaN dtype: float64
在pandas中一般用isnull、notnull检测缺失值。
series最重要的一个功能是:可以在算数运算中自动对齐不同索引的数据
obj +obj1 返回为 FuJian 30000.0 GuangDong NaN JiangSu 40000.0 JiangXi NaN ZheJiang NaN dtype: float64
Series的对象本身和索引都有一个name属性
obj1.name = 'population' obj1.index.name = 'state' obj1 返回为 state FuJian 15000.0 JiangSu 20000.0 ZheJiang NaN Name: population, dtype: float64
series也可以通过赋值的方式就地修改
2、DataFrame
dataframe既有行索引,又有列索引,可以被看作由series组成的字典(共用一个索引)
传入一个由等长列表或Numpy数组组成的字典,如果传入时不加索引,则dataframe自动加上索引
data = {'state':['JiangSu','JiangXi','ZheJiang','GuangDong'],'year':[2008,2009,2010,2011],'pop':[1.5,1.8,2.5,2.9]} frame = pd.DataFrame(data) frame frame2 = pd.dataframe(data,columns = ['year','state','pop','debt'],index = ['one','two','three','four']) frame2 返回为 state year pop 0 JiangSu 2008 1.5 1 JiangXi 2009 1.8 2 ZheJiang 2010 2.5 3 GuangDong 2011 2.9 frame2 = pd.DataFrame(data,columns = ['year','state','pop','debt'],index = ['one','two','three','four']) frame2 返回为 year state pop debt one 2008 JiangSu 1.5 NaN two 2009 JiangXi 1.8 NaN three 2010 ZheJiang 2.5 NaN four 2011 GuangDong 2.9 NaN
DataFrame一般用索引字段ix来执行
frame2.ix['four'] 返回为 year 2011 state GuangDong pop 2.9 debt NaN Name: four, dtype: object
也可以通过赋值进行修改
frame2['debt'] = 15
frame2
返回为
year | state | pop | debt | |
---|---|---|---|---|
one | 2008 | JiangSu | 1.5 | 15 |
two | 2009 | JiangXi | 1.8 | 15 |
three | 2010 | ZheJiang | 2.5 | 15 |
four | 2011 | GuangDong | 2.9 | 15 |
DataFrame另外一种数据形式是嵌套字典,被解释为:外层字典的键作为列,内层字典则作为行索引。
DataFrame的索引对象:
一般索引对象负责管理轴标签和其他元数据,在series和dataframe构建中,所用到的任何数组或者其他序列都会转换成一个index,且index不可修改(immutable)
index的方法和属性如下:
方法 | 属性 |
append | 连接另一个index对象,产生一个新的index |
diff | 计算差集,并得到一个index |
intersection | 计算交集 |
union | 计算并集 |
isin | 计算指示值是否都在参数集合的布尔型数组 |
delete | 删除索引i处的元素,并得到新的index |
drop | 删除值, |
insert | 将元素插入索引i处, |
is_monotonic | 当各元素均>=前一个元素时,返回true |
is_unique | 当index没有重复值是,返回true |
unique | 计算index中唯一值 |
3、基本功能
①重新索引 reindex
有时候在重新索引中,我们需要做一些插值处理 method,常见的method选项有
ffill---向前填充值, pad---向前搬运
bfill---向后填充, backfill----向后搬运
obj1 = pd.Series(['blue','yellow','red'],index = [1,3,5]) obj1.reindex(range(7),method = 'pad') 返回为 0 NaN 1 blue 2 blue 3 yellow 4 yellow 5 red 6 red dtype: object
而在DataFrame中,reindex既可以修改行索引,列索引,还可以两个都修改。默认索引行
import numpy as np import pandas as pd frame = pd.DataFrame(np.arange(9).reshape((3,3)),index = ['a','b','c'],columns = ['X','Y','Z']) frame 返回为 X Y Z a 0 1 2 b 3 4 5 c 6 7 8 修改行索引为 frame2 = frame.reindex(['a','b','c','d'],method = 'ffill') frame2 返回为 X Y Z a 0 1 2 b 3 4 5 c 6 7 8 d 6 7 8
行列同时修改为
DaXie = ['W','X','Z'] frame.reindex(index = ['a','b','c','d'],method = 'ffill',columns = DaXie) 返回为 W X Z a NaN 0 2 b NaN 3 5 c NaN 6 8 d NaN 6 8
其实利用ix的标签索引功能,会让程序更加简洁
frame.ix[['a','b','c','d'],DaXie] 返回为 W X Z a NaN 0.0 2.0 b NaN 3.0 5.0 c NaN 6.0 8.0 d NaN NaN NaN
②丢弃轴上的项 drop,默认丢弃行
frame = pd.DataFrame(np.arange(9).reshape((3,3)),index = ['a','b','c'],columns = ['X','Y','Z']) frame.drop('X',axis = 1) 返回为 Y Z a 1 2 b 4 5 c 7 8
③、数据运算和对齐
pandas的运算只针对索引的对象,当对象相加时,如果有不同的索引时,则结果的索引就是该索引的并集。
s1 = pd.Series([2.8,-1.3,4.5,-6.5],index = ['a','c','d','f']) s2 = pd.Series([1.6,6.3,2.5,4.5,6.7],index = ['c','b','a','e','a']) s1 + s2 返回为 a 5.3 a 9.5 b NaN c 0.3 d NaN e NaN f NaN
而在DataFrame中,对齐操作会同时发生在行和列上
对于一些NaN值,我们通常会使用fill_value来填充值
df1 = pd.DataFrame(np.arange(12).reshape(4,3),columns = list('abc')) df2 = pd.DataFrame(np.arange(20).reshape(5,4),columns = list('bcde')) df1.add(df2,fill_value = 0) 返回为 a b c d e 0 0.0 1.0 3.0 2.0 3.0 1 3.0 8.0 10.0 6.0 7.0 2 6.0 15.0 17.0 10.0 11.0 3 9.0 22.0 24.0 14.0 15.0 4 NaN 16.0 17.0 18.0 19.0
同样的,当对series或dataframe重新索引时,也可以指定填充值
df1.reindex(columns = df2.columns,fill_value = 0) 返回为 b c d e 0 1 2 0 0 1 4 5 0 0 2 7 8 0 0 3 10 11 0 0
④、DataFrame 和 Series 之间的运算
广播:不同形状的数组之间的的算数运算的执行方式。
frame = pd.DataFrame(np.arange(9).reshape((3,3)),index = ['a','b','c'],columns = ['X','Y','Z']) series = frame.ix[1] frame - series 返回为 X Y Z a -3 -3 -3 b 0 0 0 c 3 3 3
两者之间的运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播
add | 加法 |
sub | 减法 |
mul | 乘法 |
div | 除法 |
4、函数应用和映射
DataFrame的apply可以实现将函数应用到由各行或各列形成的一维数组上。
frame = pd.DataFrame(np.random.randn(4,3),columns = list('abc'),index = ['W','X','Y','Z']) 返回为 a b c W 0.417966 -1.034917 2.980040 X 0.254318 -1.566016 -0.675548 Y 0.612923 -1.983434 -0.902464 Z -1.094007 -1.674415 -2.307312 f = lambda x: x.max() - x.min() frame.apply(f) 返回为 a 1.706930 b 0.948516 c 5.287352 frame.apply(f,axis = 1)
apply还可以返回多个值组成的Series
def f(x): return pd.Series([x.min(),x.max()],index = ['min','max']) frame.apply(f) 返回为 a b c min -1.094007 -1.983434 -2.307312 max 0.612923 -1.034917 2.980040
也可以使用applymap得到frame的各个浮点值的格式化字符:
format = lambda x: '%.2f' % x frame.applymap(format) 返回为 a b c W 0.42 -1.03 2.98 X 0.25 -1.57 -0.68 Y 0.61 -1.98 -0.90 Z -1.09 -1.67 -2.31
5、排序和排名
排序一般用sort_index,将返回一个已排序的新对象:
obj = pd.Series(range(5),index = ['d','c','b','e','a']) obj.sort_index 返回为 c 1 b 2 e 3 a 4
在DataFrame中,sort_index()可以有很多种排序方式
① .sort_index() 按行排列
② .sort_index(axis = 1) 按列排列
③ 默认升序排序,降序 ascending = False
④ 在DataFrame中,使用by能够将一个或多个列的值进行排序
frame = pd.DataFrame({'c':[3,-5,2,7],'a':[2,1,0,1]}) frame.sort_index(by = 'a') 返回为 c a 2 2 0 1 -5 1 3 7 1 0 3 2
⑤ 对Series排序时,使用order 就可以,缺失值会被默认放到Series的末尾
Rank
rank 通过“为各组分配一个平均排名”来破坏这组数据的平均关系
obj = pd.Series([5,-9,3,2.5]) obj.rank() 返回为 0 4.0 1 1.0 2 3.0 3 2.0
另一种方法是,根据值在原数据中出现的顺序给出排名
obj.rank(method = 'first') obj 返回为 0 5.0 1 -9.0 2 3.0 3 2.5
降序为,obj.rank(ascending = False, method = 'max')
排名中用于破坏平级关系的method选项有:
average ,默认项,值分配平均排名
min, 最小排名
max, 最大排名
first,顺序排名
如果某个索引对应多个值,则返回一个Series;当对应单个值时,则返回一个标量值。
6、汇总和计算描述统计
df = pd.DataFrame([[2.3,1],[np.nan,2.5], [np.nan,np.nan],[0.8,-2.3]],index = ['a','b','c','d'],columns = ['one','two']) df.sum(axis = 1) 返回为 a 3.3 b 2.5 c 0.0 d -1.5 NA值会被自动排除,当引入skipna = False时,能够禁用该功能。 df.idxmax()#间接索引,最大值的索引,也有min 返回为 one a two b df.cumsum()#累积型 df.describe()#一次性产生多个统计汇总 返回为 one two count 2.00000 3.000000 mean 1.55000 0.400000 std 1.06066 2.455606 min 0.80000 -2.300000 25% 1.17500 -0.650000 50% 1.55000 1.000000 75% 1.92500 1.750000 max 2.30000 2.500000 对于非数值型,describe会产生另一种汇总统计 obj = pd.Series(['a','b','b','d']*3) obj.describe() 返回为 count 12 unique 3 top b freq 6
在series中,用corr计算两个Series中重叠、非NA、按索引对齐的相关系数
,用cov计算协方差
而DataFrame里面的corr和cov将以DataFrame形式返回矩阵,
另外,dataframe中的corrwith返回一个相关系数值Series(针对各列计算)
唯一值、值计数
唯一值 obj = pd.Series(['b','c','a','b','d','c','b','a','d']) uniques = obj.unique() uniques 返回 array(['b', 'c', 'a', 'd'], dtype=object) 值计数 obj.value_counts() 返回为 b 3 c 2 a 2 d 2 isin--判断矢量化集合的成员资格 mask = obj.isin(['a','c']) obj[mask] 返回为 1 c 2 a 5 c 7 a
7、处理缺失数据
一些NA值处理的方法:
dropna -- 标签中是否存在缺失数据对轴进行过滤
fillna -- 用指定值,插值填充缺失数据
isnull -- 返回布尔值的对象
notnull -- isnull的否定值
过滤
在Series中
from numpy import nan as NA data = pd.Series([2,3.5,NA,7]) data.dropna() 返回为 0 2.0 1 3.5 3 7.0 或者 data[data.notnull()]
在DataFrame中,dropna默认丢弃任何有缺失值的行,当传入how = ‘all’只丢弃全为NA的行,当丢弃列传入axis=1
data = pd.DataFrame([[2.,3.,5.,6.],[NA,3.4,2.5],[NA,NA,NA,NA],[2.5,NA,3.4,NA]]) cleaned = data.dropna() cleaned 返回为 0 1 2 3 0 2.0 3.0 5.0 6.0 data.dropna(how = 'all') 返回为 0 1 2 3 0 2.0 3.0 5.0 6.0 1 NaN 3.4 2.5 NaN 3 2.5 NaN 3.4 NaN
当涉及时间序列数据时,可以用thresh函数实现只留下一部分观测数据。
df = pd.DataFrame(np.random.randn(6,3)) df.ix[:3,1] = NA;df.ix[:2,3] =NA df 返回 0 1 2 3 0 0.635500 NaN 0.722100 NaN 1 0.357698 NaN -0.026564 NaN 2 -1.786260 NaN -0.233946 NaN 3 -0.072525 NaN -0.760752 NaN 4 0.259237 -0.961763 1.049663 NaN 5 0.303433 0.893801 -0.756076 NaN df.dropna(thresh =3) 返回 0 1 2 3 4 0.259237 -0.961763 1.049663 NaN 5 0.303433 0.893801 -0.756076 NaN
填充
既可以用具体值填充,也可以用字典形式填充,
df.fillna(1)
df.fillna({2:0.1,3:1})当对填充对现有对象就地修改时,只需 inplace = True
fillna还可以传入Series的平均值或中位数
data = pd.Series([1.,NA,3.5,NA,7]) data.fillna(data.sum()) 返回 0 1.0 1 11.5 2 3.5 3 11.5 4 7.0
8、层次化索引
层次化索引是指,能够以低纬度形式处理高纬度数据的一种方式,如下:
data = pd.Series(np.random.randn(10),index = [['a','a','a','b','b','c','c','c','d','d'],[1,2,3,4,5,6,7,8,9,10]])
data
返回为
a 1 0.416143 2 -2.428242 3 0.166570 b 4 1.124723 5 0.752965 c 6 -0.563679 7 -0.319499 8 -0.943406 d 9 0.185833 10 1.583854
带有MultiIndex索引的Series,可以有多种选取子集的操作,
data[:,1]
返回为
a 0.416143
层次化索引在数据重塑,透视表的生成中广泛应用
可以通过unstack方法安排到DataFrame中:
data.unstack() 返回为 1 2 3 4 5 6 7 8 9 10 a 0.416143 -2.428242 0.16657 NaN NaN NaN NaN NaN NaN NaN b NaN NaN NaN 1.124723 0.752965 NaN NaN NaN NaN NaN c NaN NaN NaN NaN NaN -0.563679 -0.319499 -0.943406 NaN NaN d NaN NaN NaN NaN NaN NaN NaN NaN 0.185833 1.583854
unstack的逆运算是stack,
data.unstack().stack()
而在dataframe中,每一个轴都可以进行分层索引
frame = pd.DataFrame(np.arange(12).reshape(4,3), index = [['a','a','b','b'],[1,2,1,2]], columns = [['Pen','Pen','Pencil'],['big','small','big']]) frame 返回为 Pen Pencil big small big a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11 各层命名如下 frame.index.names = ['price 1','price 2'] frame.columns.names = ['Species','Size'] frame 返回为
Species Pen Pencil Size big small big price 1 price 2 a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11
选列就可以用列分组完成:
frame['Pen'] 返回为 Size big small price 1 price 2 a 1 0 1 2 3 4 b 1 6 7 2 9 10
重排、分级 顺序
调整轴上各级顺序时,我们引用swaplevel函数,可以接受两个级别编号或名称,并返回互换级别的新对象
frame.swaplevel('price 1','price 2') 返回为 Species Pen Pencil Size big small big price 2 price 1 1 a 0 1 2 2 a 3 4 5 1 b 6 7 8 2 b 9 10 11
sortlevel函数能根据单个级别中的值对数据进行排序
frame.sortlevel(1) 返回 Species Pen Pencil Size big small big price 1 price 2 a 1 0 1 2 b 1 6 7 8 a 2 3 4 5 b 2 9 10 11 frame.swaplevel('price 1','price 2').sortlevel(1) 返回 Species Pen Pencil Size big small big price 2 price 1 1 a 0 1 2 2 a 3 4 5 1 b 6 7 8 2 b 9 10 11
使用DataFrame列
DataFrame中的set_index函数能将一个或多个列转换为行索引,并创建一个新的DataFrame