Reference:https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch3.html#id18
这次学习的是索引的相关内容
一、索引器
(1)表的列索引
主通过列名从DataFrameDataFrame
中取出相应的列,返回值类型为Series
, 上个代码。
df = pd.read_csv('E:\\learn python\\numpy&pandas\\learn_pandas.csv',
usecols= ['School', 'Grade', 'Name', 'Gender','Weight', 'Transfer'])
res = df['Name'].head()#取出该列,去多列类似 如df['Name','Grade'].head()
print(res)
"""
0 Gaopeng Yang
1 Changqiang You
2 Mei Sun
3 Xiaojuan Sun
4 Gaojuan You
Name: Name, dtype: object
"""
(2)序列的行索引
用 [item] 来取出序列所对应的值,若对应单个值则返回单个值,对应多个值则返回多个值,上个代码。
s = pd.Series([1, 2, 3, 4, 5, 6],
index=['a', 'b', 'a', 'a', 'a', 'c'])
res1 = s['a']
res2 = s['b']
print(res1)
"""
a 1
a 3
a 4
a 5
"""
print(res2)#2
(3)loc索引器
loc 索引器的一般形式是 loc[*, *]
,第一个代表行,第二个 * 代表列,如果单纯的写 loc[]则代表行的选择。上代码
df_demo = df.set_index('Name')
res = df_demo.head()
print(res)
"""
School Grade ... Weight Transfer
Name ...
Gaopeng Yang Shanghai Jiao Tong University Freshman ... 46.0 N
Changqiang You Peking University Freshman ... 70.0 N
Mei Sun Shanghai Jiao Tong University Senior ... 89.0 N
Xiaojuan Sun Fudan University Sophomore ... 41.0 N
Gaojuan You Fudan University Sophomore ... 74.0 N
"""
res2 = df_demo.loc['Qiang Sun']
print(res2)
"""
School Grade Gender Weight Transfer
Name
Qiang Sun Tsinghua University Junior Female 53.0 N
Qiang Sun Tsinghua University Sophomore Female 40.0 N
Qiang Sun Shanghai Jiao Tong University Junior Female NaN N
"""
觉得当*为布尔列表的时候需要注意一下,估计以后常用,上个代码
res3 = df_demo.loc[df_demo.Weight>70].head()
print(res3)
"""
School Grade Gender Weight Transfer
Name
Mei Sun Shanghai Jiao Tong University Senior Male 89.0 N
Gaojuan You Fudan University Sophomore Male 74.0 N
Xiaopeng Zhou Shanghai Jiao Tong University Freshman Male 74.0 N
Xiaofeng Sun Tsinghua University Senior Male 71.0 N
Qiang Zheng Shanghai Jiao Tong University Senior Male 87.0 N
"""
(4)iloc索引器
iloc的用法和loc的用法相同,但它是针对位置进行筛选
df_demo.iloc[1, 1] #对所传入表的第行第二列取出操作
df_demo.iloc[[0, 1], [0, 1]] # 前两行前两列进行取出操作
df_demo.iloc[1: 4, 2:4] # 进行切片操作,切片不包含结束端点
***在使用布尔列表的时候要特别注意,不能传入 Series 而必须传入序列的 values ,否则会报错。因此,在使用布尔筛选的时候还是应当优先考虑 loc 的方式。***这点要注意(感觉还是loc的方法适合我,我肯定要忘记加.values的,上个代码,两个方法做个对比)
df_demo.loc[df_demo.Weight>70].head()##loc的
df_demo.iloc[(df_demo.Weight>80).values].head()### iloc的
(5)query方法
参考文档给出这样的解释:在 pandas 中,支持把字符串形式的查询表达式传入 query 方法来查询数据,其表达式的执行结果必须返回布尔列表。在进行复杂索引时,由于这种检索方式无需像普通方法一样重复使用 DataFrame 的名字来引用列名,一般而言会使代码长度在不降低可读性的前提下有所减少。 (说白了,就是方便了,代码简洁了,上个代码。)
res = df.query('((School == "Fudan University")&'
' (Grade == "Senior")&'
' (Weight > 70))|'
'((School == "Peking University")&'
' (Grade != "Senior")&'
' (Weight > 80))')
print(res)
"""
School Grade Name Gender Weight Transfer
38 Peking University Freshman Qiang Han Male 87.0 N
66 Fudan University Senior Chengpeng Zhou Male 81.0 N
99 Peking University Freshman Changpeng Zhao Male 83.0 N
131 Fudan University Senior Chengpeng Qian Male 73.0 Y
"""
另外注意如果所选的列名有空格的话用这样的形式 col name
来进行选取。
二、多索引
多索引的形式类似这样的
先构造个行多索引
当传入元组列表或单个元组或返回前二者的函数时,需要先进行索引排序以避免性能警告:
当检索自己想要的索引条件时,用法loc和iloc方法类似,上代码,举栗子。
df_multi = df.set_index(['School', 'Grade'])
#print(df_multi.head())
df_sorted = df_multi.sort_index()
res = df_sorted.loc[('Fudan University', 'Junior')].head()
print(res)
"""
School Grade
Fudan University Junior Yanli You Female 48.0 N
Junior Chunqiang Chu Male 72.0 N
Junior Changfeng Lv Male 76.0 N
Junior Yanjuan Lv Female 49.0 NaN
Junior Gaoqiang Zhou Female 43.0 N
"""
res2 = df_sorted.loc[[('Fudan University', 'Senior'),
('Shanghai Jiao Tong University', 'Freshman')]].head()
print(res2)
"""
Name Gender Weight Transfer
School Grade
Fudan University Senior Chengpeng Zheng Female 38.0 N
Senior Feng Zhou Female 47.0 N
Senior Gaomei Lv Female 34.0 N
Senior Chunli Lv Female 56.0 N
Senior Chengpeng Zhou Male 81.0 N
"""
IndexSlice对象
主要功能是能够对每层的进行切片,slice 总共分为两种:
第一种为 loc[idx[*,*]]
型,
第二种为 loc[idx[*,*],idx[*,*]]
型
首先构造一个索引不重复的 DataFrame :
np.random.seed(0)
L1,L2 = ['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))
L3, L4 = ['D', 'E', 'F'], ['d', 'e', 'f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big', 'Small'))
df_ex = pd.DataFrame(np.random.randint(-9,10,(9,9)),
index=mul_index1,
columns=mul_index2)
loc[idx[*,*]]
型 前一个 * 表示行的选择,后一个 * 表示列的选择,上个代码。
loc[idx[*,*],idx[*,*]]
型,前一个 idx 指代的是行索引,后一个是列索引。
三、索引的常用方法
1、索引层的交换和删除
先构造一个三级索引如图
索引层的交换有swapleve
l和 reorder_levels
两种方法,前者只能交换两层,后者可以交换任意两层。
df_ex.swaplevel(0,2,axis=1).head()#列索引的第一层和第三层交换
df_ex.reorder_levels([2,0,1],axis=0).head() # 列表数字指代原来索引中的层号,原先是012,现在变为201
删除索引用droplevel
四、练习
Ex1:公司员工数据集
现有一份公司员工数据集:
1.分别只使用 query 和 loc 选出年龄不超过四十岁且工作部门为 Dairy 或 Bakery 的男性。
2 选出员工 ID 号 为奇数所在行的第1、第3和倒数第2列。
3.按照以下步骤进行索引操作:
把后三列设为索引后交换内外两层
恢复中间一层
修改外层索引名为 Gender
用下划线合并两层行索引
把行索引拆分为原状态
修改索引名为原表名称
恢复默认索引并将列保持为原表的相对位置
解:1、querry的方法
res1 = df.query( '((age<=40)&(department =="Dairy" ) & '
'(gender == "M" ))|'
'((age<=40)&(department =="Bakery" ) & '
'(gender == "M"))'
)
print(res1)
loc的方法
def conditicon(x):
condition1 = x.age <= 40
condition2_1 = x.department == 'Dairy'
condition2_2 = x.department == 'Bakery'
condition2 = condition2_1 | condition2_2
condition_3 = x.gender == 'M'
res = condition1 & condition2 & condition_3
return res
#pass
res2 = df.loc[conditicon]
print(res2)
2、
我的想法是:先用loc选出id为奇数的,再用iloc取列,代码如下
res1 = df.loc[df.EmployeeID%2==1]
res2 = res1.iloc[:,[0,2,-2]]
print(res2)
参考答案:(我就没想到…)
df.iloc[(df.EmployeeID%2==1).values,[0,2,-2]].head()
3、
好吧,我是学渣,就做了一半。
原答案:
我的半成品:
df_op = df.copy()
step_1 = df_op.set_index(df_op.columns[-3:].tolist()).swaplevel(0,2,axis=0)
print(step_1)
step_2 = step_1.reset_index(level=1)
step_3 = step_2.rename_axis(index={'gender:Gender'})
# print(step_3)
step_4 = step_3.copy()
step_4.index = step_3.index.map(lambda x:'_'.join(x))
print(step_4)
剩下一道题不做了,考试了快,得赶紧复习。