对应书本第二部分第5章Pandas高级操作第1节
逻辑运算
类似于Python的逻辑运算,我们以DataFrame其中一列进行逻辑计算,会产生一个对应的由布尔值组成的Series,真假值由此位上的数据是否满足逻辑表达式决定。例如下例中索引为0的数据值为89,大于36,所以最后值为True。
# Q1成绩大于36
df.Q1 > 36

一个针对索引的逻辑表达式会产生一个array类型数组,该数组由布尔值组成。根据逻辑表达式,只有索引为1的值为True,其余全为False
# 索引等于1
df.index == 1

除了逻辑运算,Pandas还支持组合条件的Python位运算:
~(df.Q1 < 60) & (df['team'] == 'C')

注:在Python中,位运算符包括位与(&)、位或(|)、位求反(~)、位异或(^)、左移位(<<)和右移位(>>),运行方法与规则如下:
位与运算符运算规则:0&0=0&1=1&0=0,1&1=1
位或运算符运算规则:0|1=1|0=1|1=1,0|0=0
位求反运算符运算规则:~0=1,~1=0,对于整数x有~x=-(x+1)
位异或运算符运算规则:0^0=1^1=0,0^1=1^0=1
左移位运算符运算规则:原来的所有位左移,最低位补0,相当于乘以2
右移位运算符运算规则:原来的所有位右移,最低位丢弃,最高位使用符号位填充,相当于整除2
逻辑筛选数据
切片([])、.loc[]和.iloc[]均支持上文所介绍的逻辑表达式。通过逻辑表达式进行复杂条件的数据筛选时需要注意,表达式输出的结果必须是一个布尔序列或者符合其格式要求的数据形式。例如,df.iloc[1+1]和df.iloc[lambda df: len(df)-1]计算出一个数值,符合索引的格式,df.iloc[df.index==8]返回的是一个布尔序列,df.iloc[df.index]返回的是一个索引,它们都是有效的表达式。
df[df['Q1'] == 8] # Q1等于8
df[~(df['Q1'] == 8)] # 不等于8
df[df.name == 'Ben'] # 姓名为Ben
df[df.Q1 > df.Q2]

# 表达式与切片一致
df.loc[df['Q1'] > 90, 'Q1':] # Q1大于90,显示Q1及其后所有列
df.loc[(df.Q1 > 80) & (df.Q2 < 15)] # and关系
df.loc[(df.Q1 > 90) | (df.Q2 < 90)] # or关系
df.loc[df['Q1'] == 8] # Q1等于8
df.loc[df.Q1 == 8] # Q1等于8
df.loc[df['Q1'] > 90, 'Q1'] # Q1大于90,只显示Q1

需要注意的是在进行或(|)、与(&)、非(~)运算时,各个独立逻辑表达式需要用括号括起来。
any和all对逻辑计算后的布尔序列再进行判断,序列中所有值都为True时all才返回True,序列中只要有一个值为True时any就返回True。它们还可以传入axis参数的值,用于指定判断的方向,与Pandas的axis参数整体约定一样,默认为0列方向,传入1为行方向。利用这两个方法,我们可以对整体数据进行逻辑判断,例如:
# Q1、Q2成绩全为超过80分的
df[(df.loc[:,['Q1','Q2']] > 80).all(1)]
# Q1、Q2成绩至少有一个超过80分的
df[(df.loc[:,['Q1','Q2']] > 80).any(1)]

函数筛选
# 查询最大索引的值
df.Q1[lambda s: max(s.index)] # 值为21,s就是指df.Q1这个Series
# 计算最大值
max(df.Q1.index) # 99
df.Q1[df.index==99]

df[lambda df: df['Q1'] == 8] # Q1为8的
df.loc[lambda df: df.Q1 == 8, 'Q1':'Q2'] # Q1为8的,显示 Q1、Q2
df.loc[:, lambda df: df.columns.str.len()==4] # 由真假值组成的序列(列名字符长度为4)

df.loc[:, lambda df: [i for i in df.columns if 'Q' in i]] # 列名含有'Q'的列表
df.iloc[:3, lambda df: df.columns.str.len()==2] # 由真假值组成的序列,只取前三行(iloc为自然索引)

比较函数
eq()
# 以下相当于 df[df.Q1 == 60]
df[df.Q1.eq(60)]
除了eq(),还有:
ne() # 不等于 !=
le() # 小于等于 <=
lt() # 小于 <
ge() # 大于等于 >=
gt() # 大于 >
使用示例
df[df.Q1.ne(89)] # Q1不等于89
df.loc[df.Q1.gt(90) & df.Q2.lt(90)] # and关系,Q1>90,Q2<90

另外还有一个. isin()函数,用于判断数据是否包含指定内容。可以传入一个列表,原数据只需要满足其中一个存在即可;也可以传入一个字典,键为列名,值为需要匹配的值,以实现按列个性化匹配存在值。
# isin
df[df.team.isin(['A','B'])] # 包含A、B两组的
df[df.isin({'team': ['C', 'D'], 'Q1':[36,93]})] # 复杂查询,其他值为NaN


查询df.query()
df.query(expr)使用布尔表达式查询DataFrame的列,表达式是一个字符串,类似于SQL中的where从句。
df.query('Q1 > Q2 > 90') # 直接写类型SQL where语句
df.query('Q1 + Q2 > 180')
df.query('Q1 == Q2')
df.query('(Q1<50) & (Q2>40) and (Q3>90)')
df.query('Q1 > Q2 > Q3 > Q4')
df.query('team != "C"')
df.query('team not in ("E","A","B")')
# 对于名称中带有空格的列,可以使用反引号引起来
df.query('B == `team name`')

# 支持传入变量,如大于平均分40分的
a = df.Q1.mean()
df.query('Q1 > @a+40')
df.query('Q1 > `Q2`+ @a')

df.eval()与df.query()类似,也可以用于表达式筛选:
# df.eval()用法与df.query类似
df[df.eval("Q1 > 90 > Q3 > 10")]
df[df.eval("Q1 > `Q2`+@a")]
筛选df.filter()
df.filter()可以对行名和列名进行筛选,支持模糊匹配、正则表达式
# axis为0是按行索引,1是按列名
df.filter(items=['Q1', 'Q2']) # 选择两列
df.filter(regex='Q', axis=1) # 列名包含Q的列
df.filter(regex='e$', axis=1) # 以e结尾的列
df.filter(regex='1$', axis=0) # 正则,索引名以1结尾
df.filter(like='2', axis=0) # 索引中有2的
# 索引中以2开头、列名有Q的
df.filter(regex='^2', axis=0).filter(like='Q', axis=1)

按数据类型查询
df.select_dtypes(include=['float64']) # 选择float64型数据
df.select_dtypes(include='bool')
df.select_dtypes(include=['number']) # 只取数字型
df.select_dtypes(exclude=['int']) # 排除int类型
df.select_dtypes(exclude=['datetime64'])
如果没有满足条件的数据,会返回一个仅有索引的DataFrame
网友评论