Pandas索引

ryluo 2020-06-14 01:29:22
Pandas系列

Datawhale组队学习pandas笔记

通用的原则:行用loc,列用[],位置用iloc,条件用bool/query,标量用at/iat

详细代码及运行结果链接:https://github.com/datawhalechina/joyful-pandas

以下仅做方法总结

单极索引

loc, iloc, [] 方法使用总结

loc

数据格式:

iloc:

[ ]操作符

DataFrame的[]索引

布尔索引

快速标量索引

当我们要取一个元素时,at和iat实现起来更快

区间索引

多级索引

创建多层索引

# 通过元组创建
tuples = [('A','a'),('A','b'),('B','a'),('B','b')]
mul_index = pd.MultiIndex.from_tuples(tuples, names=('Upper', 'Lower'))

# 也可以通过zip构造元素,与上面的结果一致
L1 = list('AABB')
L2 = list('abab')
tuples = list(zip(L1,L2))
mul_index = pd.MultiIndex.from_tuples(tuples, names=('Upper', 'Lower'))

# 还可以使用列表
arrays = [['A','a'],['A','b'],['B','a'],['B','b']]
mul_index = pd.MultiIndex.from_tuples(arrays, names=('Upper', 'Lower'))

# from_product两两元素组合
L1 = ['A','B']
L2 = ['a','b']
pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))

mul_index
'''
上面四种生成多级索引的方法输出的结果都是一致的
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('B', 'a'),
            ('B', 'b')],
           names=['Upper', 'Lower'])
'''

# 多级索引的使用与单级索引是一样的,直接给index赋值即可
pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index)

但是实际再数据分析的时候,会根据自己的数据自己设置多级的索引, 首先看一下数据的格式:

# 将Class和Address设置成多层索引
df_using_mul = df.set_index(['Class','Address'])
df_using_mul.head()

多层索引切片

基于上图进行索引的切片

df_using_mul.sort_index().loc['C_2','street_5']
# df_using_mul.loc['C_2','street_5'] #  直接这么获取数据会报错, 原因是索引没有排序
# df_using_mul.index.is_lexsorted() # 通过这个方法可以查看索引是否排序
# 该函数检查是否排序
#df_using_mul.sort_index().index.is_lexsorted()
# df_using_mul.loc[('C_2','street_5'):] 报错
# 当不排序时,不能使用多层切片
df_using_mul.sort_index().loc[('C_2','street_6'):('C_3','street_4')]
# 注意此处由于使用了loc,因此仍然包含右端点

df_using_mul.sort_index().loc[('C_2','street_7'):'C_3'].head()
# 注意这里切片索引的后半部分不是一个元组,但是也是合法的,表示选中该层所有元素,

两类特殊情况

df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]]
# 表示选出某几个元素,精确到最内层索引

df_using_mul.sort_index().loc[(['C_2','C_3'],['street_4','street_7']),:]
# 选出第一层在‘C_2’和'C_3'中且第二层在'street_4'和'street_7'中的行

索引层的交换

两层索引相互交换

交换前

交换后:

df_using_mul.sort_index().loc[(['C_2','C_3'],['street_4','street_7']),:]
#选出第一层在‘C_2’和'C_3'中且第二层在'street_4'和'street_7'中的行

多层交换

df_muls = df.set_index(['School','Class','Address'])
df_muls.head()
df_muls.reorder_levels([2,0,1],axis=0).sort_index().head()

#如果索引有name,可以直接使用name
df_muls.reorder_levels(['Address','School','Class'],axis=0).sort_index().head()

多层交换的结果:

索引设定

index_col参数

index_col是我们在读取csv中的一个参数,可以指定哪些是索引。

pd.read_csv('data/table.csv',index_col=['Address','School']).head()

reindex和reindex_likw

df.reindex(index=[1101,1203,1206,2402])

上图中出现NaN是因为元数据中就没有索引为1206这个数据,同理下图中的Average也没有

df.reindex(columns=['Height','Gender','Average']).head()

当出现NaN的时候,reinde可以使用method方法进行填充

df.reindex(index=[1101,1203,1206,2402],method='bfill')
#bfill表示用所在索引1206的后一个有效行填充,ffill为前一个有效行,nearest是指最近的

reindex_like的作用为生成一个横纵索引完全与参数列表一致的DataFrame,数据使用被调用的表

df_temp = pd.DataFrame({'Weight':np.zeros(5),
                        'Height':np.zeros(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID')
df_temp.reindex_like(df[0:5][['Weight','Height']])

# 如果df_temp单调还可以使用method参数
df_temp = pd.DataFrame({'Weight':range(5),
                        'Height':range(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID').sort_index()
df_temp.reindex_like(df[0:5][['Weight','Height']],method='bfill')
#可以自行检验这里的1105的值是否是由bfill规则填充

set_index和reset_index

set_index就是将某些列的值直接作为索引,先看一下原始数据

df.set_index('Class').head() # 结果如下

可以发现原来的索引ID没了,直接替换掉了,所以如果可能还需要原来的索引的话,这种方法不是很好

也可以在原索引的基础上再加上一层索引

df.set_index('Class',append=True).head() # 设置append参数为True
# 当使用与表长相同的列作为索引(需要先转化为Series,否则报错):
df.set_index(pd.Series(range(df.shape[0]))).head()

# 可以直接添加多级索引:
df.set_index([pd.Series(range(df.shape[0])),pd.Series(np.ones(df.shape[0]))]).head()

reindex

重置索引,默认重置成自然数索引

df.reset_index().head()
```python # 利用append参数可以将当前索引维持不变 df.set_index('Class',append=True).head() ```

常用索引函数

where函数

当对条件为False的单元进行填充

df.where(df['Gender']=='M').head()
# 不满足条件的行全部被设置为NaN
df.where(df['Gender']=='M').dropna().head()
# 从图中可以看出那些含有NaN的数据都被删除了

mask函数

mask函数与where功能上相反,其余完全一致,即对条件为True的单元进行填充

df.mask(df['Gender']=='M').head()  # 下图是该行代码的运行结果

df.mask(df['Gender']=='M').dropna().head()
df.mask(df['Gender']=='M',np.random.rand(df.shape[0],df.shape[1])).head()

query函数

query函数中的布尔表达式中,下面的符号都是合法的:行列索引名、字符串、and/not/or/&/|/~/not in/in/==/!=、四则运算符

df.query('(Address in ["street_6","street_7"])&(Weight>(70+10))&(ID in [1303,2304,2402])')

重复元素的处理

duplicated方法

该方法返回了是否重复的布尔列表,

df.duplicated('Class').head()

可选参数keep默认为first,即首次出现设为不重复,若为last,则最后一次设为不重复,若为False,则所有重复项为False

df.duplicated('Class',keep='last').tail()

df.duplicated('Class',keep=False).head()

drop_duplicates方法

从名字上看出为剔除重复项,这在后面章节中的分组操作中可能是有用的,例如需要保留每组的第一个值

df.drop_duplicates('Class') # 从下图中的结果上看,就是直接将后面重复的元素都删除了

# 所以删除的位置也类似于dulicated一样
df.drop_duplicates('Class',keep='last')
# 在传入多列时等价于将多列共同视作一个多级索引,比较重复项
# 意思就是两者同时重复才算重复项
df.drop_duplicates(['School','Class'])

抽样函数

samples函数

df.sample(n=5) # 按照样本数抽样

df.sample(frac=0.05) # 按照比例抽样

df.sample(n=df.shape[0],replace=True).head() # replace表示是否放回

抽样时维度控制

# axis为抽样维度,默认为0,即抽行
df.sample(n=3,axis=1).head() # 随机抽取3列

df.sample(n=3,axis=0).head() # 随机抽取三行

抽样时给样本或特征加权重

df.sample(n=3,weights=np.random.rand(df.shape[0])).head()

#以某一列为权重,这在抽样理论中很常见
df.sample(n=3,weights=df['Math']).head()

问题

一:

二:

三:

四:

五:

六:

七:

八:

练习

练习1

练习二