pandas-task03.md

索引

一、索引器

1. 表的列索引

一般通过[ ]来索引,如单列df[‘Student’],多列[]要传入列表如df[[‘School’,‘Grade’]].head()
单列也可以df.Student取出 不过这里实践的时候发现有些特殊字符的时候不可用,比如列名有空格 \n,则只能通过df[‘列名’]方式或者预先处理特殊字符解决。

2. 序列的行索引

和列索引类似,比较特别的是可以使用切片的方式取出某两个索引之间的元素,形式如s[‘c’: ‘b’: -2],这里的切片包含左右端点。

整数切片索引s[1: -1:2] 去除对应位置的值,这里同python切片一样不包含右端点。

3. loc索引器——基于 元素

1.单个元素
df_demo.loc['查询名称']

# 同时查行和列
df_demo.loc['Qiang Sun', 'School']

如果查出来唯一则返回series,查出来多个则返回dataframe

2.多个元素
df_demo.loc[['Qiang Sun','Quan Zhao'], ['School','Gender']]
3.切片
 df_demo.loc['Gaojuan You':'Gaoqiang Qian', 'School':'Gender']

需要起止点唯一,包含左右端点。

4.条件表达式

判断

df_demo.loc[df_demo.Weight>70]

是否在列表中

df_demo.loc[df_demo.Grade.isin(['Freshman', 'Senior'])]

loc方式返回的是一个bool列表
复合条件可以使用
|(或), &(且), ~(取反)

使用 | 和 or结果不同,后来发现是因为or写在了引号之外,在里面的时候结果是一样的,不过这也引发了我的思考, 既然没有报错,那么or写在外面是怎样运算的呢?后面有时间的话思考。
在这里插入图片描述

5.自定义函数、lambda表达式

传入的x是本身

def fun(x):
	 xxx

f_demo.loc[fun]

4.iloc索引器——基于位置

同loc基本相同,只不过基于位置

df_demo.iloc[1, 1] # 第二行第二列

f_demo.iloc[[0, 1], [0, 1]] # 前两行前两列

df_demo.iloc[1: 4, 2:4] # 切片不包含结束端点
 
df_demo.iloc[lambda x: slice(1, 4)] # 传入切片为返回值的函数

df_demo.iloc[(df_demo.Weight>80).values].head()

df_demo.School.iloc[1:5:2]

5.query方法

和loc条件表达式基本相同,可以相互转换。

df.query('(Grade not in ["Freshman", "Sophomore"]) and'
			'(Gender == "Male")').head()

6. 随机抽样

这个应该也可以设置个随机种子

np.random.seed(123)
df_sample.sample(3, replace = True, weights = df_sample.value)

二、多级索引

1. 多级索引及其表的结构

在这里插入图片描述

2.多级索引中的loc索引器

多级索引中的元组有一种特殊的用法,可以对多层的元素进行交叉组合后索引,但同时需要指定 loc 的列,全选则用 : 表示。其中,每一层需要选中的元素用列表存放,传入 loc 的形式为 [(level_0_list, level_1_list), cols] 。

3.IndexSlice对象

前面介绍的方法,即使在索引不重复的时候,也只能对元组整体进行切片,而不能对每层进行切片,也不允许将切片和布尔列表混合使用,引入 IndexSlice 对象就能解决这个问题。 Slice 对象一共有两种形式,第一种为 loc[idx[,]] 型,第二种为 loc[idx[,],idx[,]] 型。

4.多级索引的构造

除了使用 set_index 之外,常用的有 from_tuples, from_arrays, from_product 三种方法,它们都是 pd.MultiIndex 对象下的函数。

三、索引的常用方法

1.索引层的交换和删除

索引层的交换由 swaplevel 和 reorder_levels 完成,前者只能交换两个层,而后者可以交换任意层,两者都可以指定交换的是轴是哪一个,即行索引或列索引

2.索引属性的修改

索引名的修改、索引值的修改

rename_axis 和rename两个,分别对应修改索引名字和索引的值,对于多级索引,rename需要指定level(层)。

df2=df_ex.rename(index=lambda x:str.upper(x),
				columns={'cat':'not dog'},level=2).head()

这里顺便试验了下之前的导出格式为markdown,不过鉴于该表比较复杂,所以显示效果不太好。一般的表应该可以比较好得显示。
使用df.to_markdown()前要!pip install tabulate 和 import tabulate

(‘C’, ‘c’, ‘not dog’)(‘C’, ‘c’, ‘dog’)(‘C’, ‘d’, ‘not dog’)(‘C’, ‘d’, ‘dog’)(‘D’, ‘c’, ‘not dog’)(‘D’, ‘c’, ‘dog’)(‘D’, ‘d’, ‘not dog’)(‘D’, ‘d’, ‘dog’)
(‘A’, ‘a’, ‘ALPHA’)36-9-6-6-209
(‘A’, ‘a’, ‘BETA’)-5-33-8-3-258
(‘A’, ‘b’, ‘ALPHA’)-44-107-466
(‘A’, ‘b’, ‘BETA’)-99-685-2-9-8
(‘B’, ‘a’, ‘ALPHA’)0-91-629-7-9

3.索引的设置与重置

set_index 设置
reset_index 重置 其中drop=True 或False决定是否要把去掉的索引层丢弃

4. 索引的变形

reindex

df_reindex.reindex(index=['1001','1002','1003','1004'],columns=['Weight','Gender'])

也可以使用reindex_like

四、索引运算

1.集合的运算法则

在这里插入图片描述

2. 一般的索引运算

由于集合的元素是互异的,但是索引中可能有相同的元素,先用 unique 去重后再进行运算。

id1.intersection(id2)

id1.union(id2)

id1.difference(id2)

id1.symmetric_difference(id2)

此外,还可以使用符号

id1 & id2
id1 | id2
(id1 ^ id2) & id1
d1 ^ id2 # ^符号即对称差

df_set_in_col_1[df_set_in_col_1.id1.isin(df_set_in_col_2.id2)]

练习

Ex1:公司员工数据集

1.分别只使用 query 和 loc 选出年龄不超过四十岁且工作部门为 Dairy 或 Bakery 的男性

loc的方法

df.loc[(df.department.isin(['Dairy','Bakery']))&
		(df.age<=40)&
		(df.gender=='M')]

query的方法
一开始使用 and or的方法 但是不小心写在了条件外面 形式是‘条件1’ or ‘条件2’ 也出了结果但是和上面使用loc的不一样 后来发现写在里面才是真正满足条件

df.query('(department =="Dairy"|
		department =="Bakery")&
		gender=="M"&age<=40')
		
df2=df.query('(department in ["Dairy" , "Bakery"] ) 
		and  (gender=="M")  
		and  (age<=40)')
2.选出员工 ID 号 为奇数所在行的第1、第3和倒数第2列。
df.iloc[(df.EmployeeID%2==1).values,[0,2,-2]].head()
3.按照以下步骤进行索引操作:
  • 把后三列设为索引后交换内外两层
df_cp=df.copy()
df_cp = df_cp.set_index(df_cp.
		columns[-3:].tolist()).swaplevel(0,2,axis=0)
df_cp

  • 恢复中间一层
df_cp = df_cp.reset_index(level=1).head()
  • 修改外层索引名为 Gender
df_cp.rename_axis(index={'gender':'Gender'},axis=0).head()
  • 用下划线合并两层行索引
new_idx = df_cp.index.map(lambda x: (x[0]+'_'+x[1]))
df_cp.index = new_idx  
df_cp.head()

在这里插入图片描述

  • 把行索引拆分为原状态
df_cp.index = df_cp.index.map(lambda x:tuple(x.split('_')))
  • 修改索引名为原表名称
df_cp = df_cp.rename_axis(index=['gender', 'department'])
  • 恢复默认索引并将列保持为原表的相对位置
df_cp = df_cp.reset_index().reindex(df.columns, axis=1)

Ex2:巧克力数据集

1.把列索引名中的 \n 替换为空格。

一开始想用rename_axis这种方式+内置函数实现,但是实践下来发现没有变化?后来发现这列名估计也不是个索引所以不能用这种方式。

df.rename_axis(columns={'Cocoa\nPercent':'Cocoa Percent'}).head()

修改之后ok

s=['_'.join(str(x).split('\n')) for x in df.columns.tolist()]
df.columns=s
df.head()
2.巧克力 Rating 评分为1至5,每0.25分一档,请选出2.75分及以下且可可含量 Cocoa Percent 高于中位数的样本。

我使用的是loc 列名有空格的时候不能使用df.列名这样 于是我上小问将空格替换成了下划线。先将百分比转换成数字,不然非数值类型数据不能使用中位数函数。转换完后可以使用loc或者query进行查询。(空格问题可以用df[’ 列名’]的方式取到)

df.Cocoa_Percent=df.Cocoa_Percent.apply(lambda x:float(x[:-1])/100)

df.loc[(df.Rating<=2.75) & (df.Cocoa_Percent>df.Cocoa_Percent.median())]

query的方式

df.query('(Rating<3)&(`Cocoa_Percent`>`Cocoa_Percent`.median())')
3.将 Review Date 和 Company Location 设为索引后,选出 Review Date 在2012年之后且 Company Location 不属于 France, Canada, Amsterdam, Belgium 的样本。

首先设置索引

df.set_index(['Review Date','Company Location']).head()

在这里插入图片描述
试验了下和答案结果相同,2012年之后这个条件很简单,另外一个条件我的想法是把满足条件的的Company Location找出来就行了。简单的方式是直接加上~符号代表取反。

exclude_list=['France', 'Canada', 'Amsterdam', 'Belgium' ]
all_list=df['Company Location'].unique().tolist() 
all_list_exclude=[i for i in all_list if i not in exclude_list]

condition_1=df['Review Date']>=2012
condition_2=df['Company Location'].isin(all_list_exclude)
condition_3=df['Company Location'].isin(exclude_list)

df.loc[(condition_1)&(condition_2)]
df.loc[(condition_1)&(~condition_3)]

答案的做法

idx = pd.IndexSlice
exclude = ['France', 'Canada', 'Amsterdam', 'Belgium']
res = df.set_index(['Review Date', 'Company Location']).sort_index(level=0)
res.loc[idx[2012:,~res.index.get_level_values(1).isin(exclude)],:]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值