一、作业
作业1
#作业1
df = pd.read_csv('../joyful-pandas-master/data/company.csv')
df.head()
#分别只使用 query 和 loc 选出年龄不超过四十岁且工作部门为 Dairy 或 Bakery 的男性。
df.query("age<=40 & department in ['Dairy', 'Bakery']")
df.loc[df.age<=40].loc[df.department.isin(['Dairy', 'Bakery'])]
#选出员工 ID 号 为奇数所在行的第1、第3和倒数第2列。
df.iloc[(df.EmployeeID % 2 == 1).values, [0,2,-2]]
#把后三列设为索引后交换内外两层
df1 = df.copy()
df1_new = df1.set_index(list(df1.columns[-3:]))
df1_new.swaplevel(1,2,axis=0).head()
#恢复中间一层
df1_new.reset_index(df1_new.index.names[1])#或者
df1_new.reset_index(level=1)
df1_new.head()
#修改外层索引名为 Gender
df1_new.rename_axis(index={'gender':'Gender'}).head()
# 用下划线合并两层行索引
df1_new.index = df1_new.index.map(lambda x:'_'.join(x))#join表示字符串的连接
df1_new.head()
#把行索引拆分为原状态
df1_new.index = df1_new.index.map(lambda x:tuple(x.split('_')))#split为字符串的切开函数
df1_new.head()
#修改索引名为原表名称
#df1_new.rename_axis(index=['gender','department'])#因为只改动了'gender', 'department'??
作业2
# 1 把列索引名中的 \n 替换为空格
df.columns = pd.Index(' '.join('$'.join(list(df.columns)).split('\n')).split('$'))
df.columns
#巧克力 Rating 评分为1至5,每0.25分一档,请选出2.75分及以下且可可含量 Cocoa Percent 高于中位数的样本。
# 第一步,将百分比转化为数字类型
df['Cocoa Percent'] = df['Cocoa Percent'].str.strip('%').astype(float)/100
# 第2步,筛选
df.loc[df.Rating<=2.75].loc[df['Cocoa Percent'] > df['Cocoa Percent'].median()]
df.head()
二、索引器
2.1 表的列索引与序列的行索引
import numpy as np
import pandas as pd
df = pd.read_csv('../joyful-pandas-master/data/learn_pandas.csv',
usecols=['School', 'Grade', 'Name', 'Gender','Weight', 'Transfer'])
1 列索引,可以用df[’’],也可用df.
要取出单列,且列名中不包含空格,则可以用 .列名 取出,这和 [列名] 是等价的:
df.Name#Series,等价于df['Name']
- 序列的行索引
a 以字符串为索引的 Series,如果取出单个索引的对应元素,则可以使用 [item] ,
若 Series 只有单个值对应,则返回这个标量值,如果有多个值对应,则返回一个 Series:
s = pd.Series([1,2,3,4,5,6],index=['a','b','a','a','a','c'])
s['a']#a 1
#a 3
#a 4
#a 5
#dtype: int64
s1 = pd.Series(np.arange(1,7),dtype=np.int64)
s.values == s1.values#只能逐元素对比,直接s==s1是错误的
#array([ True, True, True, True, True, True])
#如果取出多个索引的对应元素,则可以使用 [items的列表] :
s[['c','b']]#c 6
#b 2
#dtype: int64
#如果想要取出某两个索引之间的元素,并且这两个索引是在整个索引中唯一出现,则可以使用切片,
#注意这里的切片会包含两个端点:
s['c':'b':-2]#等价于s[-1:-5:-2],且包含头尾两个元素
#c 6
#a 4
#b 2
#dtype: int64
b 以整数为索引的 Series
在使用数据的读入函数时,如果不特别指定所对应的列作为索引,那么会生成从0开始的整数索引作为默认索引
s1 = pd.Series(['a','b','c','d','e','f'])
s1
#任意一组符合长度要求的整数都可以作为索引
s1[2:6]#不包含6所指代的值
s2 = pd.Series(['a','b','c','d','e','f'],index=[1,3,1,2,6,4])
s2[1]#1 a
#1 c
#dtype: object
s2[[2,3]]#2 d
#3 b
#dtype: object
#如果使用整数切片,则会取出对应索引 位置 的值,注意这里的整数切片同 Python 中的切片一样不包含右端点:
s2[1:-1:2]#这里的1是指第2个位置,而不是序号中的'1'
#3 b
#2 d
#dtype: object
s2[2:-1:2]
#1 c
#6 e
#dtype: object
2.2 loc索引器
前面讲到了对 DataFrame 的列进行选取,下面要讨论其行的选取。
对于表而言,有两种索引器,一种是基于元素的 loc 索引器,另一种是基于位置的 iloc 索引器。
loc索引器的一般形式是loc[,] ,其中第一个代表行的选择,第二个代表列的选择,如果省略第二个位置写作loc[],这个 是指行的筛选。
其中, * 的位置一共有五类合法对象,分别是:单个元素、元素列表、元素切片、布尔列表以及函数,下面将依次说明。
先利用 set_index 方法把 Name 列设为索引,
df_demo = df.set_index('Name')
df_demo.head()#把'Name'作为列索引也就是后面的所有行索引都只能是Name这里面的元素。
- 1 为单个元素,此时,直接取出相应的行或列,如果该元素在索引中重复则结果为 DataFrame,否则为 Series
df_demo.loc['Qiang Sun']#有多个人叫此名
df_demo.loc['Qiang Sun','Weight']#这样就会把所有叫Qiang Sun的姓名与Weight显示出来。
#Name
#Qiang Sun 53.0
#Qiang Sun 40.0
#Qiang Sun NaN
#Name: Weight, dtype: float64
df_demo.loc['Quan Zhao']#名字唯一
#School Shanghai Jiao Tong University
#Grade Junior
#Gender Female
#Weight 53
#Transfer N
#Name: Quan Zhao, dtype: object
df_demo.loc['Quan Zhao','School']
#'Shanghai Jiao Tong University'
- 2, * 为元素列表,取出列表中所有元素值对应的行或列:
df_demo.loc[['Qiang Sun','Quan Zhao'],['School','Gender']]
- 3 * 为切片,如果是唯一值的起点和终点字符,那么就可以使用切片,并且包含两个端点,如果不唯一则报错:
#df_demo.loc['Qiang Sun':'Quan Zhao','School':'Gender']#报错
df_demo.loc['Gaojuan You':'Gaoqiang Qian','School':'Gender']
#如果 DataFrame 使用整数索引,其使用整数切片的时候和上面字符串索引的要求一致,都是元素切片,
#包含端点且起点、终点不允许有重复值。
df_loc_slice_demo = df_demo.copy()#把这个表重新复制一遍的意义是什么呢
df_loc_slice_demo.index = range(df_loc_slice_demo.shape[0],0,-1)#这个意思是值把这个表的索引表示为从200到1,以-1为步长的列表,其实就是200-1的倒序
df_loc_slice_demo.loc[5:3]#展示序号5-3的内容
df_loc_slice_demo.loc[3:5]# 没有返回,说明不是整数位置切片
- 4 * 为布尔列表,在实际的数据处理中,根据条件来筛选行是极其常见的,此处传入loc的布尔列表与DataFrame长度相同,且列表为 True 的位置所对应的行会被选中, False 则会被剔除。
df_demo.loc[df_demo.Weight>70].head()#df_demo.Weight>70可以直接用?
#前面所提到的传入元素列表,也可以通过isin方法返回的布尔列表等价写出,例如选出所有大一和大四的同学信息
df_demo.loc[df_demo.Grade.isin(['Freshman','Senior'])].head()
#对于复合条件而言,可以用 |(或), &(且), ~(取反) 的组合来实现,注意是两个条件之间用
#例如选出复旦大学中体重超过70kg的大四学生,或者北大男生中体重超过80kg的非大四的学生:
#先找出复旦大学中体重超过70kg的大四学生
df_demo.loc[(df_demo.School.isin(['Fudan University']))&(df_demo.Weight>70)&(df_demo.Grade.isin(['Senior']))]
#再找出北大男生中体重超过80kg的非大四的学生
df_demo.loc[(df_demo.School.isin(['Peking University']))&(df_demo.Weight>80)&~(df_demo.Grade.isin(['Senior']))]
df_demo.loc[((df_demo.School.isin(['Fudan University']))&(df_demo.Weight>70)&(df_demo.Grade.isin(['Senior'])))|((df_demo.School.isin(['Peking University']))&(df_demo.Weight>80)&~(df_demo.Grade.isin(['Senior'])))]
#分开写
condition1_1 = df_demo.School == 'Fudan University'
condition1_2 = df_demo.Weight > 70
condition1_3 = df_demo.Grade == 'Senior'
condition1 = condition1_1 & condition1_2 & condition1_3
condition2_1 = df_demo.School == 'Peking University'
condition2_2 = df_demo.Weight > 80
condition2_3 = df_demo.Grade != 'Senior'
condition2 = condition2_1 & condition2_2 & condition2_3
df_demo.loc[condition1|condition2]
- 5, * 为函数
这里的函数,必须以前面的四种合法形式之一为返回值,并且函数的输入值为 DataFrame 本身。
假设仍然是上述复合条件筛选的例子,可以把逻辑写入一个函数中再返回,需要注意的是函数的形式参数 x 本质上即为 df_demo :
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
df_demo.loc[condition]
#还支持使用 lambda 表达式,其返回值也同样必须是先前提到的四种形式之一
df_demo.loc[lambda x:'Quan Zhao', lambda x:'Gender']#'Female'
#由于函数无法返回如 start: end: step 的切片形式,故返回切片时要用 slice 对象进行包装:
df_demo.loc[lambda x: slice('Gaojuan You', 'Gaoqiang Qian')]
df_chain = pd.DataFrame([[0,0],[1,0],[-1,0]],columns=['A','B'])
df_chain
#A B
#0 0 0
#1 1 0
#2 -1 0
df_chain.loc[df_chain.A!=0,'B']=1
df_chain
#A B
#0 0 0
#1 1 1
#2 -1 1
练习:利用布尔列表选择的方法结合 DataFrame 的 dtypes 属性在 learn_pandas 数据集上实现这个功能。
练习:利用布尔列表选择的方法结合 DataFrame 的 dtypes 属性在 learn_pandas 数据集上实现这个功能。
df1 = pd.read_csv('../joyful-pandas-master/data/learn_pandas.csv')
#思路是想只要把每列的类型找出来,然后给出不同于数值类型的一个布尔值序列,但是还是有一些坑,比如dtype后不知道结果属于什么,
#不好用!=这种判断符号,然后转战用np的列表,要列表的话,每列要判断就要循环,所以又用了个列表推导式,
#再然后loc也有坑,要注意这里是取列,不能一个参数,一个参数默认是取行,这里行取所有值,所以得用:。
ind = [True if i.type != np.object_ else False for i in df1.dtypes.values ]
df1.loc[:,ind]
2 .3 iloc索引器
iloc 的使用与loc完全类似,只不过是针对位置进行筛选,在相应的 * 位置处一共也有五类合法对象,
分别是:整数、整数列表、整数切片、布尔列表以及函数,函数的返回值必须是前面的四类合法对象中的一个,其输入同样也为 DataFrame 本身。
df_demo.iloc[1,1]#'Freshman'# 第二行第二列
df_demo.iloc[[0,1],[1,2]]#第一二行第二三列
df_demo.iloc[1:4,2:4]#不包含右端点
#df_demo.iloc[df_demo.Weight>80,2]#报错,布尔列表怎么用??
df_demo.iloc[lambda x :slice(1,4)]#传入切片为返回值
#在使用布尔列表的时候要特别注意,不能传入 Series 而必须传入序列的 values ,否则会报错。
#因此,在使用布尔筛选的时候还是应当优先考虑 loc 的方式。
df_demo.iloc[(df_demo.Weight>85).values,2]#这种就可以
#Name
#Mei Sun Male
#Qiang Zheng Male
#Qiang Han Male
#Name: Gender, dtype: object
#对 Series 而言同样也可以通过 iloc 返回相应位置的值或子序列:
df_demo.School.iloc[1:5:2]
2.4 query方法
在 pandas 中,支持把字符串形式的查询表达式传入 query 方法来查询数据,其表达式的执行结果必须返回布尔列表。在进行复杂索引时,由于这种检索方式无需像普通方法一样重复使用 DataFrame 的名字来引用列名,(??什么意思?)一般而言会使代码长度在不降低可读性的前提下有所减少。?
df.query('((School == "Fudan University")&'
'( Grade == "Senior")&'
'(Weight > 70))|'
'((School == "Peking University")&'
'(Grade != "Senior")&'
'(Weight > 80))')##直接用字符串的名字
##字符串的引用要用双引号或者是反引号(1旁边的那个``),单引号会报错。
#在 query 表达式中,帮用户注册了所有来自 DataFrame 的列名,所有属于该 Series 的方法都可以被调用,和正常的函数调用并没有区别,
df.query('Weight>Weight.mean()')
#对于含有空格的列名,需要使用 `col name` 的方式进行引用。
#在 query 中还注册了若干英语的字面用法,帮助提高可读性,例如: or, and, or, is in, not in 。
df.query('(Gender == "Male")and''(Grade not in ["Freshman","Sophomore"])')
#此外,在字符串中出现与列表的比较时, ==和!=分别表示元素出现在列表和没有出现在列表,等价于is in和not in
df.query('Grade == ["Junior", "Senior"]').head()
#对于 query 中的字符串,如果要引用外部变量,只需在变量名前加 @ 符号。
low = 70,high = 80
df.query('Weight.between(@low,@high)',engine = 'python')#报错,未找出原因
2.5 随机抽样
sample 函数中的主要参数为 n, axis, frac, replace, weights ,前三个分别是指抽样数量、抽样的方向(0为行、1为列)和抽样比例(0.3则为从总体中抽出30%的样本)。replace 和 weights 分别是指是否放回和每个样本的抽样相对概率,当 replace = True 则表示有放回抽样。
df_sample = pd.DataFrame({'id':list('abcde'),'value':[1,2,3,4,90]})
df_sample
df_sample.sample(3,replace = True,weights = df_sample.value)##?意思是1%,2%,。。90%?
#id value
#4 e 90
#4 e 90
#4 e 90
三、多级索引
3.1 多级索引及其表的结构
np.random.seed(0)
multi_index = pd.MultiIndex.from_product([list('ABCD'),df.Gender.unique()],names = ('School','Gender'))
#注意names用()括起来,是元组形式
multi_column = pd.MultiIndex.from_product([['Heignt','Weight'],df.Grade.unique()],names = ('Indicator', 'Grade'))
df_multi = pd.DataFrame(np.c_[(np.random.randn(8,4)*5+163).tolist(),(np.random.randn(8,4)*5+63).tolist()],
index = multi_index, columns = multi_column).round(1)#round(1)保留一位小数
print(df_multi)
#这里的行索引和列索引都是 MultiIndex 类型,只不过 索引中的一个元素是元组 而不是单层索引中的标量。
#例如,行索引的第四个元素为 ("B", "Male") ,列索引的第二个元素为 ("Height", "Senior"),
#与单层索引类似, MultiIndex 也具有名字属性,图中的School和Gender分别对应了表的第一层和第二层行索引的名字,
#Indicator 和 Grade 分别对应了第一层和第二层列索引的名字。
df_multi.index.names#FrozenList(['School', 'Gender'])
df_multi.index.values#array([('A', 'Female'), ('A', 'Male'), ('B', 'Female'), ('B', 'Male'),
# ('C', 'Female'), ('C', 'Male'), ('D', 'Female'), ('D', 'Male')],
# dtype=object),元组的形式
df_multi.columns.names#FrozenList(['Indicator', 'Grade'])
#如果想要得到某一层的索引,则需要通过 get_level_values 获得:
df_multi.index.get_level_values(0)#,取值只能是0,1
#Index(['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D'], dtype='object', name='School')
3.2 多级索引中的loc索引器
在原表中,不是上面的df_multi,将学校和年级设为索引,此时的行为多级索引(学校,年纪),列为单级索引,由于默认状态的列索引不含名字,因此对应于刚刚图中 Indicator 和 Grade 的索引名位置是空缺的。
df_multi1 = df.set_index(['School','Grade'])
df_multi1
#由于多级索引中的单个元素以元组为单位,因此之前在第一节介绍的loc和iloc方法完全可以照搬,只需把标量的位置替换成对应的元组,
#不过在索引前最好对 MultiIndex 进行排序以避免性能警告:
df_multi1 = df_multi1.sort_index()
df_multi1.loc[('Fudan University', 'Junior')].head()
df_multi1.loc[[('Fudan University', 'Junior'),('Shanghai Jiao Tong University', 'Freshman')]]
df_multi1.loc[('Fudan University', 'Junior'),('Gender')]
df_multi1.loc[df_multi1.Weight > 70].head()
##练习:与单层索引类似,若存在重复元素,则不能使用切片,请去除重复索引后给出一个元素切片的例子。怎么去重??
#想要得到所有北大和复旦的大二大三学生,可以如下写出:
res = df_multi1.loc[(['Peking University','Fudan University'],['Sophomore','Junior']),:]
res.head()
#选出北大的大三学生和复旦的大二学生:
res1 = df_multi1.loc[[('Peking University','Junior'),('Fudan University','Sophomore')]]
res1
3.3 IndexSlice对象
IndexSlice 对象可以对每层进行切片,也允许将切片和布尔列表混合使用
np.random.seed(0)
L1,L2 = ['A','B','C'] ,['a','b','c']
mut_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))
L3,L4 = ['D','E','F'] ,['d','e','f']
mut_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big', 'Small'))
df_ex = pd.DataFrame(np.random.randint(-9,10,(9,9)),
index=mut_index1,columns=mut_index2)
df_ex
#为了使用 silce 对象,先要进行定义:
idx = pd.IndexSlice#??这是什么意思
#【a】 loc[idx[*,*]] 型
#这种情况并不能进行多层分别切片,前一个 * 表示行的选择,后一个 * 表示列的选择,与单纯的 loc 是类似的:
df_ex.loc[idx['C':,['D','F']]]#‘C'后面加了:,就会出蓝Upper栏,下面显示C,不加:,就没有
#:代表什么意思
#另外,也支持布尔序列的索引:
df_ex.loc[idx['A':'C':2,],lambda x: x.sum()>0]#列和大于0,切片会包含’C‘
#【b】 loc[idx[*,*],idx[*,*]] 型
#这种情况能够分层进行切片,前一个 idx 指代的是行索引,后一个是列索引。
df_ex.loc[idx[:'A','b':],idx['E':]]
3.4 多级索引的构造
常用的有 from_tuples, from_arrays, from_product 三种方法,它们都是 pd.MultiIndex 对象下的函数。
from_tuples 指根据传入由元组组成的列表进行构造
from_arrays 指根据传入列表中,对应层的列表进行构造:
from_product 指根据给定多个列表的笛卡尔积进行构造:
上面两种都要把所有组合写完,而笛卡尔积只要写对应值就可
my_tuple = [('a','cat'),('a','dog'),('b','cat'),('b','dog')]
pd.MultiIndex.from_tuples(my_tuple,names=['First','Second'])
#from_arrays 指根据传入列表中,对应层的列表进行构造:
my_array = [list('aabb'),['cat','dog']*2]
pd.MultiIndex.from_arrays(my_array,names=['First','Second'])
#from_product 指根据给定多个列表的笛卡尔积进行构造:
my_List1 = ['a','b']
my_List2 = ['cat','dog']
pd.MultiIndex.from_product([my_List1,my_List2],names=['First','Second'])
#上面两种都要把所有组合写完,而笛卡尔积只要写对应值就可
四、索引的常用方法
4.1 索引层的交换和删除
#构造三级索引
np.random.seed(0)
L1,L2,L3 = ['A','B'],['a','b'],['alpha','beta']#这里的个数决定行层级的个数,为2*2*2
mul_index1 = pd.MultiIndex.from_product([L1,L2,L3],names=('Upper','Lower','Extra'))
L4,L5,L6 = ['C','D'],['c','d'],['cat','dog']#这里的个数决定列层级的个数,为2*2*2
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
索引层的交换由 swaplevel 和 reorder_levels 完成,前者只能交换两个层,而后者可以交换任意层,
两者都可以指定交换的是轴是哪一个,即行索引或列索引,注意是只交换索引,不交换表里的数字内容
df_ex.swaplevel(0,2,axis=1)#Big和Other这两层交换了
df_ex.reorder_levels([2,0,1],axis=0)#行索引的第三层变为第一,第一层变为第二,第二层变为第三
#若想要删除某一层的索引,可以使用 droplevel 方法:
df_ex.droplevel(0,axis=1)#删除列的第一层Big
df_ex.droplevel([0,2],axis=0)
4.2 索引属性的修改
通过rename_axis可以对索引层的名字进行修改,常用的修改方式是传入字典的映射
df_ex.rename_axis(index={'Upper':'Changed_row'},columns={'Other':'Changed_Col'})
通过 rename 可以对索引的值进行修改,如果是多级索引需要指定修改的层号 level
df_ex.rename(columns={'cat':'not_cat'},level=2)#'cat'只在第二层,如果是其他层,则修改无意义。还是原来的
传入参数也可以是函数,其输入值就是索引元素
df_ex.rename(index=lambda x: str.upper(x),level=2)
#练一练,在 rename_axis 中使用函数完成与例子中一样的功能。尝试失败,不知道单个元素传入要怎么用函数
#df_ex.rename_axis({df_ex.index.values:lambda x:['Changed_row',x[1],x[2]]},{df_ex.columns.values:lambda x:[x[0],x[1],'Changed_Col']})
map ,它是定义在 Index 上的方法,与前面 rename 方法中层的函数式用法是类似的,只不过它传入的不是层的标量值,而是直接传入索引的元组,这为用户进行跨层的修改提供了遍历
df_temp = df_ex.copy()
new_idx = df_temp.index.map(lambda x: (x[0],
x[1],
str.upper(x[2])))
df_temp.index = new_idx
df_temp#小写改大写
# map 的另一个使用方法是对多级索引的压缩
new_idx = df_temp.index.map(lambda x: (x[0]+'-'+
x[1]+'-'+
x[2]))
df_temp.index = new_idx
df_temp#行索引名变为:A-a-ALPHA
#同时,也可以反向地展开:
new_idx = df_temp.index.map(lambda x:tuple(x.split('-')))#split为字符串的切开函数
df_temp.index = new_idx
df_temp#行索引又分开
4.3 索引的设置与重置
索引的设置可以使用 set_index 完成,这里的主要参数是 append ,表示是否来保留原来的索引,
直接把新设定的添加到原索引的内层:
df_new = pd.DataFrame({'A':list('aacd'),
'B':list('PQRT'),
'C':[1,2,3,4]})
df_new
#索引的设置可以使用 set_index 完成,这里的主要参数是 append ,表示是否来保留原来的索引,
#直接把新设定的添加到原索引的内层:
df_new.set_index('A')#不加append表示不保留原来的索引
df_new.set_index('A', append=True)#保留了原来的0123
#可以同时指定多个列作为索引:
df_new.set_index(['A','B'])
#如果想要添加索引的列没有出现在其中(新的索引列),那么可以直接在参数中传入相应的 Series :
my_index = pd.Series(list('WXYZ'), name='D')
df_new = df_new.set_index(['A', my_index])
df_new
#reset_index 是 set_index 的逆函数,其主要参数是 drop ,表示是否要把去掉的索引层丢弃,而不是添加到列中:
df_new.reset_index(['D'])#不加drop,为不丢弃D的意思
df_new.reset_index(['D'], drop=True)#丢掉了D
#如果重置了所有的索引,那么 pandas 会直接重新生成一个默认索引:
df_new.reset_index()#默认的0123索引
4.4. 索引的变形
在某些场合下,需要对索引做一些扩充或者剔除,更具体地要求是给定一个新的索引,把原表中相应的索引对应元素填充到新索引构成的表中。
#例如,下面的表中给出了员工信息,
#需要重新制作一张新的表,要求增加一名员工的同时去掉身高列并增加性别列:
df_reindex = pd.DataFrame({"Weight":[60,70,80],
"Height":[176,180,179]},
index=['1001','1003','1002'])
df_reindex
df_reindex.reindex(index=['1001','1002','1003','1004'],
columns=['Weight','Gender'])
五、 索引运算
由于集合的元素是互异的,但是索引中可能有相同的元素,先用 unique 去重后再进行运算。下面构造两张最为简单的示例
df_set_1 = pd.DataFrame([[0,1],[1,2],[3,4]],
index = pd.Index(['a','b','a'],name='id1'))
df_set_2 = pd.DataFrame([[4,5],[2,6],[7,1]],
index = pd.Index(['b','b','c'],name='id2'))
id1, id2 = df_set_1.index.unique(), df_set_2.index.unique()#去掉索引的重复
id1#Index(['a', 'b'], dtype='object', name='id1')
id2#Index(['b', 'c'], dtype='object', name='id2')
id1.intersection(id2)#Index(['b'], dtype='object')
id1.symmetric_difference(id2)#Index(['a', 'c'], dtype='object')
#上述的四类运算还可以用等价的符号表示代替如下:
id1 & id2#交
id1 | id2#并
(id1 ^ id2) & id1#差,id1-id2#值为'a'
id1 ^ id2 # ^符号即对称差,为A+B-(AB)
#若两张表需要做集合运算的列并没有被设置索引,一种办法是先转成索引,运算后再恢复,另一种方法是利用 isin 函数,
#例如在重置索引的第一张表中选出id列交集的所在行:
df_set_in_col_1 = df_set_1.reset_index()
df_set_in_col_2 = df_set_2.reset_index()
df_set_in_col_1
#id1 0 1
#0 a 0 1
#1 b 1 2
#2 a 3 4
df_set_in_col_2
df_set_in_col_1[df_set_in_col_1.id1.isin(df_set_in_col_2.id2)]