import numpy as np
import pandas as pd
一般通过[]来实现,通过[列名]可以从DataFrame中取出相应的列,返回值为Series
df=pd.read_csv('',usecols=['School', 'Grade', 'Name', 'Gender','Weight','Transfer'])
df['Name'].head()
#如果要取出多个列,可以通过`[列名组成的列表]`,返回值为一个DataFrame
#从表中取出姓名和性别两列
df[['Gender','Name']].head()
#取出单列可以使用`.列名`取出,与`[列名]`是等价的
df.Name.head
[a]以字符串为索引的Series
如果取出单个索引对应元素,可以使用[item],
若Serie只有单个值对应,则返回这个标量值,
如果有多个值对应,则返回一个Series
s=pd.Series([1,2,3,4,5,6],index=['a','b','a','a','a','c'])
s['a']
Out[8]:
a 1
a 3
a 4
a 5
如果取出多个索引对应的元素,则可以使用[items的列表]
#取出两个索引之间的元素,并且这两个索引是在整个索引中唯一出现,则可以使用切片
s['c':'b':-2]
#这里的切片包含两个端点
如果前后端点的值存在重复,即非唯一值,需要经过排序才能使用切片
try:
s['a':'b']
except Exception as e:
Err_Msg=e
Err_Msg
s.sort_index()['a':'b']
[b]以整数为索引的Series
在使用数据的读入函数的时候,如果不特别指定所对应的列作为索引,那么会生成从0开始的整数索引作为默认索引
s=pd.Series(['a','b','c','d','e','f'],index=[1,3,1,2,5,4])
s[1]
s[[2,3]]
如果使用整数切片则会取出对应索引位置的值
这里的切片不包含右端点
s[1:-1:2]
3 b
2 d
不要把纯浮点以及任何混合类型作为索引,否则可能会在具体的操作时报错或者返回非预期的结果
前面讲到了对DataFrame的列进行选取
下面进行对行的选取
对表而言有两种索引器
loc索引器一般形式是loc[*,*],第一个*表示行的选取,第二个*表示列的选取
*的位置一共有五类合法对象:单个元素,元素列表,元素切片,布尔列表以及函数
df_demo=df.set_index('Name')
df_demo.head()
[a]*为单个元素,如果该元素在索引中重复则结果为DataFrame,否则为Series
df_demo.loc['Qiang Sun']#多个人叫这个名字返回DataFrame
df_demo.loc['Quan Zhao']#名字唯一返回Series
#同时选择行
df_demo.loc['Qiang Sun','School']#返回Series
df_demo.loc['Quan Zhao','School']#返回单个元素
[b]*为元素列表
df_demo.loc[['Qiang Sun','Quan Zhao'],['School','Gender']]
[c]*为切片
df_demo.loc['Gaojuan You':'Gaoqiang Qian','School':'Gender']
df_loc_slice_demo=df_demo.copy()
df_loc_slice_demo.index=range(df_demo.shape[0],0,-1)
df_loc_slice_demo.loc[5:3]
df_loc_slice_demo.loc[3:5]#没有返回,说明不是整数位置切片
df_demo.loc[df_demo.Weight > 70].head()
df_demo.loc[df_demo.Grade.isin(['Freshman','Senior'])].head()
|(或),&(且),~(取反)的组合来实现#分别求出每个条件的同学
condition_1_1=df_demo.School=='Fudan University'
condition_2_1=df_demo.Grade=='Senior'
condition_3_1=df_demo.Weight>70
condition_1=condition_1_1&condition_1_2&condition_1_3
condition_2_1=df_demo.School=='Peking University'
condition_2_2=df_demo.Grade=='Senior'
condition_2_3=df_demo.Weight>80
condition_2=condition_2_1&(~condition_2_2)&condition_2_3
df_demo.loc[condition_1|condition_2]
select_dtype是一个实用函数,能够从表中选出相应类型的列,若要选出所有数值型的列,只需使用.select_dtypes(‘number’),请利用布尔列表选择的方法结合DataFrame的dtypes属性在learn_pandas数据集上实现这个功能
[e]*为函数
这里的函数,必须以前面的四种合法形式之一为返回值,并且函数的输入值为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=df_demo.School=='Peking University'
condition_2_2=df_demo.Grade=='Senior'
condition_2_3=df_demo.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']
#由于函数无法返回如start:end:step的切片形式,故返回切片时要用slice对象进行包装
df_demo.loc[lambda x:slice('Gaojuan You','Gaoqiang Qian')]
#series可以使用`loc`索引
【Warning】不要用链式赋值
在对表或者序列赋值时,应当在使用一层索引器后直接进行赋值操作,这样由于进行多次索引后赋值是赋在临时返回的copy副本上的,而没有真正修改元素从而报出SettingWithCopyWarning警告
df_chain=pd.DataFrame([[0,0],[1,0],[-1,0]],column=list('AB'))
df_chain
import warnings
with warnings.catch_warnings():
warnings.filterwarnings('error')
try:
df_chain[df_chain.A!=0].B=1#使用方括号列索引后,再使用点的列索引
except Warning as w:
Warning_Msg=w
print(Warning_Msg)
df_chain.loc[df.chain.A!=0,'B']=1
iloc的使用与loc完全类似,只不过是针对位置进行筛选,在相应的*位置处一共也有五类
分别是:整数、整数列表、整数切片、布尔列表以及函数,函数的返回值必须是前面的四类合法对象中的一个,其输入同样也为DataFrame本身
df_demo.iloc[1,1]
#第二行第二列
df_demo.iloc[[0,1],[0,1]]
#前两行前两列
df_demo.iloc[1:4,2:4]df_demo.iloc[1:4,2:4]
#切片不包含结束端点
df_demo.iloc[lambda x:slice(1,4)]
#传入切片为返回值的函数
#使用布尔筛选的时候应当优先考虑loc的方式
#选出体重超过80kg的学生
df_demo.iloc[(df_demo.Weight>80).values].head()
df_demo.School.iloc[1]
df_demo.School.iloc[1:5:2]
在pandas中,支持把字符串形式的查询表达式传入query方法来查询数据,其表达式的执行结果必须返回布尔列表。
df.query('((School == "Fudan University"&'
'(Grade == Senior)&'
'(Weight > 70 ))|'
'((School == "Peking University"&'
'(Grade != "Senior")&'
'(Weight > 80))')
df.query('Weight > Weight.mean()').head()
对于含有空格的列名,需要使用col name的方式进行引用
同时,在query中还注册了若干英语的字面用法,帮助提高可用性
例如or , and , in ,not in
==等价于in
!=等价于not in
df.query('(Grade not in ["Freshman", "Sophomore"]) and (Gender == "Male")').head()
df.query('Grade == ["Junior","Senior"]').head()
#对于query中的字符串,如果要引用外部变量,只需要在变量名前加@符号
low,high=70,80
df.query('(Weight >= @low)&(Weight <= @high)')
如果把DataFrame的每一行看作一个样本,或者把每一列看作一个特征,再把整个DataFrame看作总体,想要对样本或特征进行随机抽样就可以用sample函数。
同时,由于许多统计特征在等概率不放回的简单随机抽样条件下,是总体统计特征的无偏估计,比如样本均值和总体均值
sample函数中的主要参数为n, axis, frac, replace, weights,前三个分别是指抽样数量、抽样的方向(0为行、1为列)和抽样比例(0.3则为从总体中抽出30%的样本)。
replace和weights分别是指是否放回和每个样本的抽样相对概率,当replace = True则表示有放回抽样。例如,对下面构造的df_sample以value值的相对大小为抽样概率进行有放回抽样,抽样数量为3。
df_sample=pd.DataFrame({'id': list('abcde'), 'value': [1, 2, 3, 4, 90]})
df_sample.sample(3,replace=True,weights=df_sample.value)
np.random.seed(0)
multi_index = pd.MultiIndex.from_product([list('ABCD'), df.Gender.unique()], names=('School', 'Gender'))
multi_column = pd.MultiIndex.from_product([['Height', '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 + 65).tolist()],
index = multi_index, columns = multi_column).round(1)
df_multi

这里的行索引和列索引都是MultiIndex类型,只不过索引中的一个元素是元组而不是单层索引中的标量。
与单层索引类似,MultiIndex也具有名字属性
索引的名字和值属性分别可以通过names和values获得
如果想要得到某一层的索引,则需要通过get_level_values获得
df_multi.index.names
df_multi.columns.names
df_multi.index.values
df_multi.columns.values
df_multi.index.get_level_values(0)
无论是单层还是多层,用户都无法通过index_obj[0] = item的方式来修改元素,也不能通过index_name[0] = new_name的方式来修改名字
将学校和年级设为索引,此时的行为多级索引,列为单级索引,由于默认状态的列索引不含名字,因此对应于刚刚图中Indicator和Grade的索引名位置是空缺的。
df_multi = df.set_index(['School', 'Grade'])
df_multi.head()
由于多级索引中的单个元素以元组为单位,因此之前在第一节介绍的 loc 和 iloc 方法完全可以照搬,只需把标量的位置替换成对应的元组。
当传入元组列表或单个元组或返回前二者的函数时,需要先进行索引排序以避免性能警告
with warnings.catch_warnings():
warnings.filterwarnings('error')
try:
df_multi.loc[('Fudan University', 'Junior')].head()
except Warning as w:
Warning_Msg = w
Warning_Msg
df_sorted = df_multi.sort_index()
df_sorted.loc[('Fudan University', 'Junior')].head()
df_sorted.loc[[('Fudan University', 'Senior'), ('Shanghai Jiao Tong University', 'Freshman')]].head()
df_sorted.loc[df_sorted.Weight > 70].head() # 布尔列表也是可用的
df_sorted.loc[lambda x:('Fudan University','Junior')].head()
在单级索引中只要切片端点元素是唯一的,那么就可以进行切片,但在多级索引中,无论元组在索引中是否重复出现,都必须经过排序才能使用切片,否则报错
try:
df_multi.loc[('Fudan University', 'Senior'):].head()
except Exception as e:
Err_Msg = e
Err_Msg
df_sorted.loc[('Fudan University', 'Senior'):].head()
df_unique = df.drop_duplicates(subset=['School','Grade']).set_index(['School', 'Grade'])
df_unique.head()
try:
df_unique.loc[('Fudan University', 'Senior'):].head()
except Exception as e:
Err_Msg = e
Err_Msg
df_unique.sort_index().loc[('Fudan University', 'Senior'):].head()
可以对多层的元素进行交叉组合后索引,
但同时需要指定loc的列,全选则用:表示。
其中,每一层需要选中的元素用列表存放,
传入loc的形式为[(level_0_list, level_1_list), cols]。
#例如,想要得到所有北大和复旦的大二大三学生,可以如下写出:
res = df_multi.loc[(['Peking University', 'Fudan University'], ['Sophomore', 'Junior']), :]
res.head()
#选出北大的大三学生和复旦的大二学生:
res = df_multi.loc[[('Peking University', 'Junior'), ('Fudan University', 'Sophomore')]]
res.head()
即使在索引不重复的时候,也只能对元组整体进行切片,而不能对每层进行切片,也不允许将切片和布尔列表混合使用,引入IndexSlice对象就能解决这个问题。
Slice对象一共有两种形式
loc[idx[*,*]]型,loc[idx[*,*],idx[*,*]]型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)
df_ex

定义slice对象
idx = pd.IndexSlice
【a】loc[idx[*,*]]型
前一个*表示行的选择,后一个*表示列的选择,与单纯的loc是类似的:
df_ex.loc[idx['C':, ('D', 'f'):]]
df_ex.loc[idx[:'A', lambda x:x.sum()>0]] # 列和大于0
【b】loc[idx[*,*],idx[*,*]]型
df_ex.loc[idx[:'A', 'b':], idx['E':, 'e':]]
#但需要注意的是,此时不支持使用函数:
try:
df_ex.loc[idx[:'A', lambda x: 'b'], idx['E':, 'e':]]
except Exception as e:
Err_Msg = e
Err_Msg
除了使用set_index之外,
常用的有from_tuples, from_arrays, from_product三种方法,它们都是pd.MultiIndex对象下的函数。
my_tuple = [('a','cat'),('a','dog'),('b','cat'),('b','dog')]
pd.MultiIndex.from_tuples(my_tuple, names=['First','Second'])
my_array = [list('aabb'), ['cat', 'dog']*2]
pd.MultiIndex.from_arrays(my_array, names=['First','Second'])
my_list1 = ['a','b']
my_list2 = ['cat','dog']
pd.MultiIndex.from_product([my_list1, my_list2], names=['First','Second'])
构造一个三级索引
np.random.seed(0)
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
索引层的交换由swaplevel和reorder_levels完成,前者只能交换两个层,而后者可以交换任意层
df_ex.swaplevel(0,2,axis=1).head() # 列索引的第一层和第三层交换
df_ex.reorder_levels([2,0,1],axis=0).head() # 列表数字指代原来索引中的层
droplevel方法:df_ex.droplevel(1,axis=1)
df_ex.droplevel([0,1],axis=0)
通过rename_axis可以对索引层的名字进行修改,常用的修改方式是传入字典的映射:
df_ex.rename_axis(index={'Upper':'Changed_row'},
columns={'Other':'Changed_Col'}).head()
如果是多级索引需要指定修改的层号level:
df_ex.rename(columns={'cat':'not_cat'}, level=2).head()
传入参数也可以是函数,其输入值就是索引元素:
df_ex.rename(index=lambda x:str.upper(x), level=2).head()
reset_index是set_index的逆函数,其主要参数是drop,表示是否要把去掉的索引层丢弃,而不是添加到列中:
如果重置了所有的索引,那么pandas会直接重新生成一个默认索引:
还有一个与reindex功能类似的函数是reindex_like,其功能是仿照传入的表索引来进行被调用表索引的变形。
df_existed = pd.DataFrame(index=['1001','1002','1003','1004'], columns=['Weight','Gender'])
df_reindex.reindex_like(df_existed)
S
A
.
i
n
t
e
r
s
e
c
t
i
o
n
(
S
B
)
=
S
A
∩
S
B
⇔
{
x
∣
x
∈
S
A
a
n
d
x
∈
S
B
}
\rm S_A.intersection(S_B) = \rm S_A \cap S_B \Leftrightarrow \rm \{x|x\in S_A\, and\, x\in S_B\}
SA.intersection(SB)=SA∩SB⇔{x∣x∈SAandx∈SB}
S
A
.
u
n
i
o
n
(
S
B
)
=
S
A
∪
S
B
⇔
{
x
∣
x
∈
S
A
o
r
x
∈
S
B
}
\rm S_A.union(S_B) = \rm S_A \cup S_B \Leftrightarrow \rm \{x|x\in S_A\, or\, x\in S_B\}
SA.union(SB)=SA∪SB⇔{x∣x∈SAorx∈SB}
S
A
.
d
i
f
f
e
r
e
n
c
e
(
S
B
)
=
S
A
−
S
B
⇔
{
x
∣
x
∈
S
A
a
n
d
x
∉
S
B
}
\rm S_A.difference(S_B) = \rm S_A - S_B \Leftrightarrow \rm \{x|x\in S_A\, and\, x\notin S_B\}
SA.difference(SB)=SA−SB⇔{x∣x∈SAandx∈/SB}
S
A
.
s
y
m
m
e
t
r
i
c
_
d
i
f
f
e
r
e
n
c
e
(
S
B
)
=
S
A
△
S
B
⇔
{
x
∣
x
∈
S
A
∪
S
B
−
S
A
∩
S
B
}
\rm S_A.symmetric\_difference(S_B) = \rm S_A\triangle S_B\Leftrightarrow \rm \{x|x\in S_A\cup S_B - S_A\cap S_B\}
SA.symmetric_difference(SB)=SA△SB⇔{x∣x∈SA∪SB−SA∩SB}
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.intersection(id2)
id1.union(id2)
id1.difference(id2)
id1.symmetric_difference(id2)
若两张表需要做集合运算的列并没有被设置索引,一种办法是先转成索引,运算后再恢复,另一种方法是利用isin函数,例如在重置索引的第一张表中选出id列交集的所在行
df_set_in_col_1[df_set_in_col_1.id1.isin(df_set_in_col_2.id2)]