pandas-task03.md

文章目录

  • 索引
    • 一、索引器
      • 1. 表的列索引
      • 2. 序列的行索引
      • 3. loc索引器——基于 元素
        • 1.单个元素
        • 2.多个元素
        • 3.切片
        • 4.条件表达式
        • 5.自定义函数、lambda表达式
      • 4.iloc索引器——基于位置
      • 5.query方法
      • 6. 随机抽样
    • 二、多级索引
      • 1. 多级索引及其表的结构
      • 2.多级索引中的loc索引器
      • 3.IndexSlice对象
      • 4.多级索引的构造
    • 三、索引的常用方法
      • 1.索引层的交换和删除
      • 2.索引属性的修改
        • 索引名的修改、索引值的修改
      • 3.索引的设置与重置
      • 4. 索引的变形
    • 四、索引运算
      • 1.集合的运算法则
      • 2. 一般的索引运算
    • 练习
      • Ex1:公司员工数据集
        • 1.分别只使用 query 和 loc 选出年龄不超过四十岁且工作部门为 Dairy 或 Bakery 的男性
        • 2.选出员工 ID 号 为奇数所在行的第1、第3和倒数第2列。
        • 3.按照以下步骤进行索引操作:
      • Ex2:巧克力数据集
        • 1.把列索引名中的 \n 替换为空格。
        • 2.巧克力 Rating 评分为1至5,每0.25分一档,请选出2.75分及以下且可可含量 Cocoa Percent 高于中位数的样本。
        • 3.将 Review Date 和 Company Location 设为索引后,选出 Review Date 在2012年之后且 Company Location 不属于 France, Canada, Amsterdam, Belgium 的样本。

索引

一、索引器

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写在外面是怎样运算的呢?后面有时间的话思考。
pandas-task03.md_第1张图片

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. 多级索引及其表的结构

pandas-task03.md_第2张图片

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’) 3 6 -9 -6 -6 -2 0 9
(‘A’, ‘a’, ‘BETA’) -5 -3 3 -8 -3 -2 5 8
(‘A’, ‘b’, ‘ALPHA’) -4 4 -1 0 7 -4 6 6
(‘A’, ‘b’, ‘BETA’) -9 9 -6 8 5 -2 -9 -8
(‘B’, ‘a’, ‘ALPHA’) 0 -9 1 -6 2 9 -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.集合的运算法则

pandas-task03.md_第3张图片

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()

pandas-task03.md_第4张图片

  • 把行索引拆分为原状态
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()

pandas-task03.md_第5张图片
试验了下和答案结果相同,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)],:]

你可能感兴趣的:(pandas,python,数据分析)