一、索引器
1、表的列索引
In [4]: df['Name'].head() #表示单纯找到一列
2、序列的行索引
以字符串为索引
In [7]: s = pd.Series([1, 2, 3, 4, 5, 6],
...: index=['a', 'b', 'a', 'a', 'a', 'c'])
s['a']
以整数为索引
In [15]: s = pd.Series(['a', 'b', 'c', 'd', 'e', 'f'],
....: index=[1, 3, 1, 2, 5, 4])
s[[2,3]]
3、loc索引器
对于表而言,有两种索引器,一种是基于 元素 的 loc 索引器,另一种是基于 位置 的 iloc 索引器;loc 索引器的一般形式是 loc[*, *] ,其中第一个 * 代表行的选择,第二个 * 代表列的选择,如果省略第二个位置写作 loc[*] ,这个 * 是指行的筛选。其中, * 的位置一共有五类合法对象,分别是:单个元素、元素列表、元素切片、布尔列表以及函数
*单个元素
df_demo = df.set_index('Name') #用set_index把Name列设为索引
df_demo.loc['Qiang Sun'] #找叫做这个名字的人的信息
df_demo.loc['Qiang Sun', 'School'] #同时选择行和列
*元素列表
df_demo.loc[['Qiang Sun','Quan Zhao'], ['School','Gender']] #多个行元素和多个列元素
*切片
对序列切片,如果是唯一值的起点和终点字符,就可以使用切片
df_demo.loc['Gaojuan You':'Gaoqiang Qian', 'School':'Gender']
*为布尔列表
列表为 True 的位置所对应的行会被选中, False 则会被剔除
选出体重超过70kg的学生:
df_demo.loc[df_demo.Weight>70].head() #直接可以表示列
选出所有大一和大四的同学 isin
df_demo.loc[df_demo.Grade.isin(['Freshman', 'Senior'])].head()
复合条件,|或,& 且,~ 取反
condition_1_1 = df_demo.School == 'Fudan University'
condition_1_2 = df_demo.Grade == 'Senior'
condition_1_3 = df_demo.Weight > 70
condition_1 = condition_1_1 & condition_1_2 & condition_1_3
condition_2 = condition_2_1 & (~condition_2_2) & condition_2_3
df_demo.loc[condition_1 | condition_2]
*为函数(和上面的布尔列表原理相似)
def condition(x):
....: condition_1_1 = x.School == 'Fudan University'
....: condition_1_2 = x.Grade == 'Senior'
....: condition_1_3 = x.Weight > 70
....: condition_1 = condition_1_1 & condition_1_2 & condition_1_3
....: condition_2_1 = x.School == 'Peking University'
....: condition_2_2 = x.Grade == 'Senior'
....: condition_2_3 = x.Weight > 80
....: condition_2 = condition_2_1 & (~condition_2_2) & condition_2_3
....: result = condition_1 | condition_2
....: return result
In [43]: df_demo.loc[condition]
还支持匿名函数
df_demo.loc[lambda x:'Quan Zhao', lambda x:'Gender'] #其实也可以看成是行,列
df_demo.loc[lambda x: slice('Gaojuan You', 'Gaoqiang Qian')] #用匿名函数做切片
四、iloc索引器
位置索引(感觉很容易的样子)
df_demo.iloc[1, 1] # 第二行第二列
df_demo.iloc[[0, 1], [0, 1]] # 前两行前两列
df_demo.iloc[1: 4, 2:4] # 切片不包含结束端点
df_demo.iloc[lambda x: slice(1, 4)] # 传入切片为返回值的函数,这个跟上面loc也可以应用匿名函数很像,返回切片
df_demo.School.iloc[1:5:2] #start、end、step
df_demo.iloc[(df_demo.Weight>80).values].head() #如果用iloc需要后面加上.values
五、query方法
一、查询体重超过均值的学生
df.query('Weight > Weight.mean()').head()
这个让我想到了最近正在学的SQL当中也可以实现的功能
SELECT weight
FROM table
WHERE weight>(SELECT MEAN(weight) FROM table)
在 query 中还注册了若干英语的字面用法,帮助提高可读性,例如:or, and, or, is in, not in
df.query('(Grade not in ["Freshman", "Sophomore"]) and'
'(Gender == "Male")').head()
在query中引入外部变量,在变量名前加 @ 符号
low, high =70, 80
df.query('Weight.between(@low, @high)').head()
六、随机抽样
如果把 DataFrame 的每一行看作一个样本,或把每一列看作一个特征,再把整个 DataFrame 看作总体,想要对样本或特征进行随机抽样就可以用 sample 函数
df_sample = pd.DataFrame({'id': list('abcde'),
'value': [1, 2, 3, 4, 90]})
df_sample.sample(3, replace = True, weights = df_sample.value) #sample 函数中的主要参数为 n, axis, frac, replace, weights ,前三个分别是指抽样数量、抽样的方向(0为行、1为列)和抽样比例(0.3则为从总体中抽出30%的样本), replace = True 则表示有放回抽样,
二、多级索引
索引的构造
建立二级列索引
df1 = DataFrame(np.random.randint(0,150,size=(4,6)),
index = list('东南西北'),
columns=[['python','python','math','math','En','En'],['期中','期末','期中','期末','期中','期末']])
显示构造multiIndex
例1:In [118]: my_list1 = ['a','b']
In [119]: my_list2 = ['cat','dog']
In [120]: pd.MultiIndex.from_product([my_list1,
.....: my_list2],
.....: names=['First','Second'])
.....:
Out[120]:
MultiIndex([('a', 'cat'),
('a', 'dog'),
('b', 'cat'),
('b', 'dog')],
names=['First', 'Second'])
例2:
df4 = DataFrame(np.random.randint(0,150,size=(8,12)),
columns = pd.MultiIndex.from_product([['模拟考','正式考'],
['数学','语文','英语','物理','化学','生物']]),
index = pd.MultiIndex.from_product([['期中','期末'],
['雷军','李斌'],
['测试一','测试二']]))
多级索引中的loc索引器
把学校和年级设为索引,此时行为多级索引,列为单机索引
df_multi = df.set_index(['School', 'Grade'])
df_sorted = df_multi.sort_index() #当传入元组列表或单个元组或返回前二者的函数时,需要先进行索引排序以避免性能警告
其余都可以照搬loc和iloc方法
在多级索引中的元组有一种特殊的用法,可以对多层的元素进行交叉组合后索引,但同时需要指定 loc 的列,全选则用 : 表示。其中,每一层需要选中的元素用列表存放,传入 loc 的形式为 [(level_0_list, level_1_list), cols] 。例如,想要得到所有北大和复旦的大二大三学生,可以如下写出:
res = df_multi.loc[(['Peking University', 'Fudan University'],
....: ['Sophomore', 'Junior']), :]
北大的大三学生和复旦的大二学生
res = df_multi.loc[[('Peking University', 'Junior'),
.....: ('Fudan University', 'Sophomore')]]
这个地方是真的绕
IndexSlice对象(这个地方实在是看不懂了)
前面介绍的方法,即使在索引不重复的时候,也只能对元组整体进行切片,而不能对每层进行切片,也不允许将切片和布尔列表混合使用,引入 IndexSlice 对象就能解决这个问题
三、索引的常用方法
索引层的交换和删除
建立一个三级索引
L1,L2,L3 = ['A','B'],['a','b'],['alpha','beta']
mul_index1 = pd.MultiIndex.from_product([L1,L2,L3],
.....: names=('Upper', 'Lower','Extra'))
L4,L5,L6 = ['C','D'],['c','d'],['cat','dog']
mul_index2 = pd.MultiIndex.from_product([L4,L5,L6],
.....: names=('Big', 'Small', 'Other'))
df_ex = pd.DataFrame(np.random.randint(-9,10,(8,8)),
.....: index=mul_index1,
.....: columns=mul_index2)
df_ex
Out[10]:
Big C D
Small c d c d
Other cat dog cat dog cat dog cat dog
Upper Lower Extra
A a alpha -3 6 -5 0 5 -2 -3 -4
beta -9 6 4 -7 2 -4 -4 0
b alpha 6 3 2 3 4 3 3 9
beta -8 9 -9 2 -6 -1 -2 -1
B a alpha -3 -5 3 -5 2 4 8 6
beta 7 -1 0 -9 0 5 -1 -9
b alpha -4 -7 -9 -6 -3 -8 7 -8
beta 8 -2 -5 -8 -5 9 6 2
索引层的交换由swaplevel 和 reorder_levels完成,前者只能交换两个层,而后者可以交换任意层,两者都可以指定交换的是轴是哪一个,即行索引或列索引
df_ex.swaplevel(0,2,axis=1).head() # 列索引的第一层和第三层交换
df_ex.droplevel(1,axis=1) #删除某一层的索引
索引属性的修改
df_ex.rename_axis(index={'Upper':'Changed_row'},
.....: columns={'Other':'Changed_Col'}).head()
通过 rename 可以对索引的值进行修改,如果是多级索引需要指定修改的层号 level :
In [133]: df_ex.rename(columns={'cat':'not_cat'},
.....: level=2).head()
索引的设置与重置
reset_index 是 set_index 的逆函数,其主要参数是 drop ,表示是否要把去掉的索引层丢弃,而不是添加到列中
df_new.set_index(['A', 'B'])
df_new.reset_index(['D'])
df_new.reset_index() #如果重置了所有的索引,那么 pandas 会直接重新生成一个默认索引:0123
索引的变形
df_reindex = pd.DataFrame({"Weight":[60,70,80],"Height":[176,180,179]},index=['1001','1003','1002'])
...: df_reindex
...:
Out[11]:
Weight Height
1001 60 176
1003 70 180
1002 80 179
假装分割线
df_reindex.reindex(index=['1001','1002','1003','1004'],
...: columns=['Weight','Gender'])
Out[12]:
Weight Gender
1001 60.0 NaN
1002 80.0 NaN
1003 70.0 NaN
1004 NaN NaN
四、索引运算
这个运算可以适用在多个表同时运算的时候,例如有两张表 A 和 B ,它们的索引都是员工编号,现在需要筛选出两表索引交集的所有员工信息