pandas基础篇
本文pandas模块调用时默认写为pd
一、进入pandas世界
1、Series 是一种一维的数组型对象,它包含了一个值的序列(与 numpy 中的类型相似),并且包含了数据标签称为索引(index)
2、默认生成的索引是从 0 到 N-1(N 是数据的长度)
a = pd.Series([1,3,5,7,9])
print(a)
print(a.index)
RangeIndex(start=0, stop=5, step=1)
二、创建索引序列
1、a = pd.Series([1,2,4,6],index=[‘a’,’b’,’c’,’d’,’e’])。注意必须长度对应
a = pd.Series([1,3,5,7,9],index=[1,2,3,4,5])
print(a)
2、通过索引可以使用标签进行索引
a = pd.Series(np.arange(5).reshape(5),index=[1,2,3,4,5])
print(a[[1,4]])
3、索引序列的简单运算
a = pd.Series(np.arange(5).reshape(5),index=[1,2,3,4,5])
print(a>0) #bool
print(a[a>0]) #符合项
print(a*2)
print(np.exp(a))
print(1 in a)
4、使用字典生成一个 Series 。 key 作为标签,value作为序列
a = {'a':1,'b':3,'c':7,'d':9}
print(pd.Series(a))
5、你可以传递自己排序好的 index 将序列从新排序,多出的返回 Nan ,没有的不在索引。如同重构
a = {'a':1,'b':3,'c':7,'d':9}
print(pd.Series(a,index=['b','a','d','m']))
三、检查是否缺失数据,给自身和标签(索引)对象命名
1、Series 对象本身和其索引都具有 name 属性。
a = {'a':1,'b':3,'c':7,'d':9}
b=pd.Series(a,index=['b','a','d','m'])
b.name = 'yyy'
b.index.name = 'xxx'
print(b.name)
print(b.index)
2、使用 isnull 函数检查缺失,非缺失返回 true。使用 notnull 非缺失返回 false
a = {'a':1,'b':3,'c':7,'d':9}
b=pd.Series(a,index=['b','a','d','m'])
print(pd.isnull(b)) #返回对应的布尔序列
b[pd.isnull(b)] = 1 #对空值从新赋值填充
四、二维序列DataFrame
1、使用字典来形成 DataFrame。字典嵌套列表
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
print(pd.DataFrame(a))
2、对二维序列进行按照指定的顺序对 axis1 进行排列,columns,与一维的Series中操作类似
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
print(pd.DataFrame(a,columns=['i','c','u']))
3、可以同时进行 axis0 和 axis1
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
print(pd.DataFrame(a,columns=['i','c','u'],index=[1,2,3]))
4、对于大型的 DataFrame。使用 head 方法将会只选出头部的部分行 。eg:a.head()
五、二维序列的索引
1、列直接用标签进行索引
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
b = pd.DataFrame(a)
print(b[['a','c']])
#或print(b.a)
2、行进行标签索引,使用 loc 进行选取
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
b = pd.DataFrame(a)
print(b.loc[[0,2]])
3、列的引用是可以直接修改的
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
b = pd.DataFrame(a)
b[['a','b','m']]=1
print(b)
4、用索引序列对二维序列进行值的填充或替换
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
b = pd.DataFrame(a)
#可多可少,用index对应去换
c = pd.Series([0,0,0,0],index=[0,1,2,3])
b['a'] = c
print(b)
5、判断列的值,并增加一个布尔列
a = {'a':[1,2,3],'b':[3,2,4],'c':[7,3,2]}
b = pd.DataFrame(a)
b['bool'] = b.c == 3
print(b)
6、删除用 del
del b.bool或del b[‘bool’]
7、 字典嵌套字典的序列生成。将 key 作为高纬度,即列标签。value 中的 key 作为行标签
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a)
print(b)
8、对 7 中按行排序或抽取
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3])
print(b)
9、与 series 类似,dataframe 的 values 属性会将包含在 dataframe 中的数据以二维 ndarray 的形式返回
六、dataframe 构造函数的有效输入
序列 | 描述 |
---|---|
2D ndarray | 数据的矩阵,行列的标签时可选参数 |
数组、列表、元组构成的字典 | 每个序列成为 dataframe 的第一列,所有序列必须长度相等 |
numpy 结构化、记忆化数组 | 与数组构成的字典一致 |
series 构成的字典 | 每个值成为一列,每个 series 的索引联合起来形成结果的行索引,也可以显示的传递索引 |
字典或 series 构成的列表 | 列表中的一个元素形成 dataframe 的一行,字典键或 series 索引联合起来形成 dataframe 的列标签 |
列表元组构成的列表 | 与 2D ndarray 的情况一致 |
其它 dataframe | 如果不显式的传递索引,则会使用原 dataframe 的索引 |
numpy maskedarray | 与 2D ndarray 的情况类似,但隐蔽值会在结果 dataframe 中成为 nan(缺失值) |
七、索引对象
1、对于任意索引序列,其索引对象是不可变的,因此用户无法修改索引对象
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3])
b.index[1] = 'd' #TypeError
2、一些索引对象的方法和属性
方法或属性 | 描述 |
---|---|
append | 将额外的索引对象粘贴到原索引后,产生新的索引 |
difference | 计算两个索引的差集 |
intersection | 计算两个索引的交集 |
union | 计算两个索引的并集 |
isin | 计算表示每一个值是否在传值容器中的布尔数组 |
delete | 将位置 i 的元素删除,并产生新的索引 |
drop | 根据传参删除指定索引值,并产生新的索引 |
insert | 在位置 i 插入元素,并产生新的索引 |
is_monotonic | 如果索引序列递增则返回 True |
is_unique | 如果索引序列唯一则返回 true |
unique | 计算索引的唯一值序列 |
八、重建索引
1、对一个索引,对于一个一维索引(series),可以使用 reindex 对其重新排序,如果没有的标签则重新构造一个
c = [1,2,3,4,5]
d = pd.Series(c,index=[1,2,3,4,5])
e = d.reindex([3,1,5,6,6])
print(e)
2、对于顺序数据,比如时间序列等,在重建索引时可能需要插值或填值。Method 可选参数允许我们使用诸如 ffill 等方法在重建索引时插值
c = [1,2,3,4,5]
d = pd.Series(c,index=[1,2,3,4,5])
e = d.reindex(range(6),method='ffill')
print(e)
3、列可以使用 columns 关键字进行重建索引
c = pd.DataFrame(np.arange(9).reshape(3,3),index=[1,2,3],columns=['a','b','c'])
d = c.reindex(columns=['b','a','d'])
print(d)
4、 我们更深入的探索时,你可以使用 loc 进行更加简洁的标签索引
frame = pd.DataFrame(np.arange(9).reshape((3,3)),index=['a','b','c'], columns=['ohio','texas','california'])
print(frame)
frame.loc[['d','c','b','b'],['texas','utah','california']]
5、reindex(重建索引) 常用方法
方法 | 描述 |
---|---|
Index | 新建作为索引的序列,可以是索引实例或任意其它序列型 python 数据结构,索引使用时无需复制 |
method | 插值方式:ffill 为前向填充,bfill 为后向填充 |
fill_value | 通过重新索引引入缺失数据时使用替代值 |
limit | 当前向或后向填充时,所需填充的最大尺寸间隙(以元素数量) |
tolerance | 当前向或后向填充时,所需填充的不精确匹配下的最大尺寸间隙(以绝对数字距离) |
level | 匹配 multiindex 级别的简单索引,否则选择子集 |
copy | 如果为 true,即使新索引等于旧索引,也总是复制底层数据;如果是false,则在索引相同时不要复制数据 |
九、轴向上删除条目
1、如果你已经拥有索引数组或不含条目的列表,在轴向上删除一个或更多的条目就非常容易。但这样操作需要一些数据操作和集合逻辑。使用 drop 方法会返回一个指示值,或轴向上删除值的新对象
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
print(b)
c= b.drop([4,5])
print(c)
2、1 中默认的 axis 是 0,可以加参数 axis 或 columns
c= b.drop(['b'],axis=1)
print(c)
3、对 1 中,可以直接加参数 inplace=True 直接对原序列进行操作。直接将原序列修改
b.drop(['b'],axis=1,inplace=True)
print(b)
十、索引选择和过滤
*注意[x]此为下标索引,[[x]]此为神奇索引或标签索引注意区分
1、按数值选择相应的,不符合的会被替换成 NaN
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
print(b[b>3])
2、 直接索引或切片索引
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
print(b)
print(b[['a']])#标签索引
print(b.loc[[2]])#标签索引axis=0
print(b[1]) #KeyError: "None of [Int64Index([1], dtype='int64')] are in the [columns]"下标索引只能对一维
print(b[:2]) #默认低维索引,即axis=0
3、 布尔索引
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
print(b)
print(b>3)#返回布尔序列
4、对于 3中,利用布尔索引从新赋值,直接对原序列从新赋值
b[b>3] = 1
print(b)
十一、更加方便的选择数据
1、 主要针对二维序列操作
2、 loc 为轴标签索引,iloc 为整数索引。参数分别沿维度上升。*注意下面例子
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
print(b)
print(b.loc[[1,3],['a','b']])#全为标签
print(b.iloc[[1,3],[1,0,1]]) #全为下标
print(b.loc[1:3,'a':'c']) #切片标签索引,全包
print(b.iloc[:2,:5]) #切片索引,前包后不包,同列表,超界不填充
3、dataframe 常见索引选项。df 为对象序列
选项 | 描述 |
---|---|
df[val] | 从 dataframe 中选择单列或列序列,特殊情况下的遍历,布尔数组(过滤行),切片(切片行)或布尔值 dataframe(根据某些标准设置的值) |
df.loc[val] | 根据标签选择 dataframe 的单行或多行 dataframe 的 |
df.loc[:,val] | 根据标签选择单列或多列 |
df.loc[val1,val2] | 同时选择行和列的一部分 |
df.iloc[where] | 根据整数位置选择单行或多行 |
df.iloc[:,where] | 根据整数位置选择单列或多列 |
df.iloc[where_i,where_j] | 根据整数位置选择行和列 |
df.at[label_i,label_j] | 根据行列标签选择单个标量值 |
df.iat[i,j] | 根据整数选择单个标量值 |
reindex 方法 | 通过标签选择行或列(需要传入轴参数 axis=x) |
get_value,set_value 方法 | 根据行和列的标签设置单个值 |
十二、pandas 中的算数和数据对齐
1、 在 pandas 中使用算数同 numpy 中一样,是对应位置的元素分别去运算。对于没有交叠的位置上,内部数据会对齐并产生缺失值
2、 在进行数据运算的过程中,由于对齐产生的缺失值会对后续的算数操作产生影响,因此需要对缺失值进行填充。可以在算数运算操作中传入填充值 fill_value 参数,进行填充
a = {'a':{1:1,2:2,3:3},'b':{0:3,1:2,2:4},'c':{2:7,5:3,6:2}}
b = pd.DataFrame(a,index=[0,1,2,3,4,5])
b[pd.isnull(b)] = 1
print(b)
c = pd.DataFrame(np.arange(15).reshape(5,3),columns=['b','c','d']) print(c)
d = b.add(c,fill_value=1) #注意只对b缺失部分进行填充
print(d)
3、在算数前加 r 可以翻转算数(接2中代码)
d = b.add(c) #等价于 d = c.radd(b)
4、 注意在重建索引或者标签时也可以使用填充值(接2中代码)
d = b.reindex(columns=c.columns,fill_value=0)
print(d)
5、 灵活的算数方法
方法 | 描述 |
---|---|
Add,radd | 加法 |
Sub,rsub | 减法 |
Div,rdiv | 除法 |
Floordiv,rfloordiv | 整除 |
Mul,rnul | 乘法 |
Pow,rpow | 幂次方,(乘方**) |
6、广播机制,当我们用 arr-arr[0]时减法在每一行都安装对应元素进行了操作(依次向下),这就是所谓的广播机制
c = pd.DataFrame(np.arange(15).reshape(5,3),columns=['b','c','d'])
print(c)
d = c-c.iloc[0]
7、 对 6 来说如果你想进行对列上的操作可以传入轴参数
d = c.sub(c['b'],axis=0)#或axis=’index’
print(d)
8、 numpy 的通用函数(逐元素数组方法)对 pandas 对象同样有效
9、 使用 dateframe 中的 apply 方法将一个函数传入序列,将函数应用到一行,或一列的一维数组上。即对行或列进行操作。可以传递轴参数 axis=x 或 axis=‘具体的轴’
c = pd.DataFrame(np.arange(15).reshape(5,3),columns=['b','c','d'])
print(c)
d = lambda x : max(x)-min(x)
e = c.apply(d)
print(e)
10、假设你想要根据 frame(一个序列对象)中的每个浮点数计算一个格式化字符串,可以使用 applymap 方法
a = pd.DataFrame(np.random.randn(4,3),columns=list('efg'),index=list('abcd'))
print(a)
b = lambda x: '%.2f' %x
c = a.applymap(b)
print(c) #使用applymap作为函数名是因为series有map方法。比如将一个逐元素的函数应用到series上
d = a['e'].map(b)
print(d)
十三、排序和排名
1、在 series 中的排序。sort_index 方法对标签进行排序。sort_values 对数值进行排序
a = pd.Series(range(4),index=[2,1,3,0])
print(a)
print(a.sort_index())#标签排序
print(a.sort_values())#值排序
print(a.sort_values(ascending=False))#降序排序
2、对于在 dataframe 中的标签排序同 1,不过可以传递轴参数,进行按不同轴排序
3、对于在 dataframe 中的值排序,你可以传递一列或多列作为排序键,传递参数为 by。同时可以按照不同轴排序。注意:此时的排序方式为按照排序轴内相同类别的和
a = pd.DataFrame(np.arange(25).reshape(5,5),index=['c','a',0,5,3],columns=['a','c','e','b','d'])
print(a)
print(a.sort_values(by=['a','c'])) #按照ac行的和排序
print(a.sort_values(by=['a','c'],axis=0)) #行的排序为按照acebd列的和排序,下去查找标签为数字的传参
4、对于在 series 中的排名。通过 rank 进行排名。默认以平均数排名。加入 ascending=false进行降序排名。常见传入的参数如下,使用 method 传入 。
排名中的平级关系打破方法。需要去一一应证好好体会
方法 | 描述 |
---|---|
average | 默认:在每组中分配平均排名,相同元素平均相同 |
min | 对整组数使用最小排名。即用最小的那个数值开始排序 |
max | 对整组数使用最大排序。即用最大的那个数开始走 |
first | 按照数值的出现持续排名。即如果正序则以 1 为位置起始,分给最小数。同元素谁在前排名在前 |
dense | 类似于 method=‘min’,但组间排名总是增加 1,而不是相等元素相同 |
a = pd.Series([7,-5,7,4,2,0,4])
print(a)
print(a.rank(method='max'))
print(a.rank(method='min'))
5、在 dataframe 中。按照轴参数不同,对于行或列进行位置排名
a = pd.DataFrame(np.arange(25).reshape(5,5),index=['c','a',0,5,3],columns=['a','c','e','b','d'])
print(a)
print(a.rank(axis=1)) #按照行进行次序排序
6、查看是否有重复标签的轴索引。使用 is_unique 属性,不重复则返回 true
a = pd.DataFrame(np.arange(6).reshape(2,3),index=[1,0],columns=['a','b','a'])
print(a)
print(a.index.is_unique)
print(a.columns.is_unique)
十四、描述性统计的概述与计算
1、对于存在空值的计算,同 numpy,计算过程中会忽略空值。如果想不忽略空值,则需要加 skipna=false,达到禁用 skipna。空值的生成(numpy.nan)
a = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]], index=['a','b','c','d'],columns=['one','two'])
print(a.sum())#默认以axis=0,即按列计算
print(a.sum(axis=1,skipna=False)) #不忽略情况下,nan与任何值进行计算结果都是空值
2、 常用的归约方法
方法 | 描述 |
---|---|
Axis | 归约轴,0 为行向(列中计算),1 为列向(行中计算) |
Skipna | 排除缺失值,默认为 true |
level | 如果轴是多层索引的(multiindex),该参数可以缩减分组层级 |
3、 汇总统计。返回相关的统计结果
a = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]], index=['a','b','c','d'],columns=['one','two'])
print(a)
print(a.idxmin()) #返回最小的索引值
print(a.describe()) #一次性产生多个汇总统计,对于非字符型数据,会参数另一种汇总统计
4、 常见的描述性统计和汇总统计
方法 | 描述 |
---|---|
count | 非Na值的个数 |
describe | 计算series或dataframe各列的汇总统计集合 |
min,max | 计算最小值、最大值 |
argmin,argmax | 分别计算最小值、最大值所在的索引位置(整数) |
idxmin,idxmax | 分别计算最小值或最大值的索引标签 |
quantile | 计算样本的从0到1间的分位数 |
sum | 加和 |
mean | 均值 |
median | 中位数(50%分数位) |
mad | 平均值的平均绝对偏差 |
prod | 所有值的积 |
var | 值的样本方差 |
std | 值的样本标准差 |
skew | 样本偏度(第三时刻)值 |
kurt | 样本峰度(第四时刻)的值 |
cumsum | 累计值 |
cummin,cummax | 累计值的最小值或最大值 |
cumprod | 值的累计积 |
diff | 计算第一个算数差值(对时间序列有用) |
pct_change | 计算百分比 |
5、相关性和协方差。Series的corr方法计算的是两个series中重叠的、非Na的、按索引对齐的值的相关性。相应的cov计算的是协方差。写法为a.corr(b)
6、另一方面,dataframe的corr和cov方法会分别以dataframe的形式返回相关性和协方差矩阵
7、使用dataframe的corrwith方法,你可以计算出dataframe中的行或列与另一个序列或dataframe的相关性。该方法传入一个series时,会返回一个含有为每列计算相关性值的series
十五、唯一值、计数和成员属性
1、使用unique函数,返回唯一值
a = pd.Series([1,2,2,4,2,4,1,8],index=['a','c','d','a','a','e','c','g'])
print(a)
print(a.unique()) #[1 2 4 8]
2、使用value_counts计算包含值的个数(接1中代码)
print(a.value_counts())#计算相同值的个数
3、为了方便,返回的series会按照数量降序排序。Value_counts也是有效的pandas顶层方法,可以用于任意的数组或序列(接1中代码)
print(pd.value_counts(a,sort=False))
4、isin执行向量化的成员属性检查,还可以将数据集以series或dataframe一列的形式过滤为数据集的值子集
a = pd.Series([1,2,2,4,2,4,1,8],index=['a','c','d','a','a','e','c','g'])
print(a)
print(a.isin([1,3])) #检测1,3是否在a中返回bool
print(a[a.isin([1,3])]) #返回是1,3的值的序列
5、与isin相关的Index.get_indexer方法。可以提供一个索引数组,这个索引数组可以将可能非唯一值数组转换为另一个唯一值数组。
a = pd.Series(['c','a','b','b','c','a']) #可能非唯一值数组
b = pd.Series(['c','b','a']) #提供的索引数组
print(a)
print(b)
c = pd.Index(b).get_indexer(a)
print(c) #[0 2 1 1 0 2]
6、唯一值、计数和集合成员属性方法
方法 | 描述 |
---|---|
isin | 计算表征series中每个值是否包含于传入序列的布尔值数组 |
match | 计算数组中每个值的整数索引,形成一个唯一值数组。有助于数据对齐和json类型的操作 |
unique | 计算series值中的唯一值数组,按照观察顺序返回 |
value_counts | 返回一个series,索引是唯一值序列,值是计数个数,按照个数降序排序 |
7、组合使用。比如在某些情况下,你可能想要计算dataframe多个相关列的直方图,如下面例子。你可以将pandas.value_counts传入dataframe的apply函数可以得到
a = pd.DataFrame({'a':[1,3,4,3,4],'b':[2,3,1,2,3],'c':[1,5,2,4,4]})
b = a.apply(pd.value_counts).fillna(0)
print(a)
print(b)
返回
a b c a b c
0 1 2 1 1 1.0 1.0 1.0
1 3 3 5 2 0.0 2.0 1.0
2 4 1 2 3 2.0 2.0 0.0
3 3 2 4 4 2.0 0.0 2.0
4 4 3 4 5 0.0 0.0 1.0
这里,结果中行标签是所有列中出现的不同值,数值则是这些不同值在每个列中出现的次数