04_Pandas高级操作(上)
复杂查询
逻辑运算
对DataFrame其中一列进行逻辑计算,会产生一个对应的由布尔值组成的Series,真假值由此位上的数据是否满足逻辑表达式决定。
df.tip > 2.0
# # sex
# Female False
# Male False
# Male True
# Male True
# Female True
# ...
# Male True
DataFrame的逻辑运算
df.loc[:,'total_bill':'tip']>5
# # total_bill tip
# sex
# Female True False
# Male True False
# Male True False
# Male True False
# Female True False
# ... ... ...
# Male True True
# Female True False
# Male True False
# Male True False
# Female True False
除了逻辑运算,Pandas还支持组合条件的Python位运算
~(df.tip <2) & (df['day']=='Sat')
# sex
# Female False
# Male False
# Male False
# Male False
# Female False
# ...
# Male True
# Female True
# Male True
# Male False
# Female False
# Length: 244, dtype: bool
逻辑筛选数据
切片([])、.loc[]和.iloc[]均支持逻辑表达式。通过逻辑表达式进行复杂条件的数据筛选时需要注意,表达式输出的结果必须是一个布尔序列或者符合其格式要求的数据形式。
df[df['tip'] == 2] # tip等于2 (返回DataFrame)
# total_bill tip smoker day time size
# sex
# Male 8.77 2.0 No Sun Dinner 2
# Male 13.37 2.0 No Sat Dinner 2
# Male 12.69 2.0 No Sat Dinner 2
# Male 16.31 2.0 No Sat Dinner 3
# Male 13.81 2.0 Yes Sat Dinner 2
# Male 13.03 2.0 No Thur Lunch 2
# Male 15.95 2.0 No Thur Lunch 2
# .........
df[~(df['tip'] == 2)] # tip不等于2
df[df.Q1 > df.Q2]# .loc[]的一些示例
df.loc[df['tip'] > 2,'tip':] # 返回DataFrame,tip后面的所有列
any和all对逻辑计算后的布尔序列再进行判断,序列中所有的值都为True时all才返回True,序列中只要有一个值为True时any就返回True。可以传入axis参数的值,用于指定判断的方向。
# tip size都大于2(返回DataFrame)
df[(df.loc[:,['tip','size']] > 2).all(1)]
# tip size至少一个大于2
df[(df.loc[:,['tip','size']] > 2).any(1)]
函数筛选
可以在表达式处使用lambda函数,默认变量是其操作的对象。如果操作的对象是—个DataFrame,那么变量就是这个DataFrame;如果是一个Series,那么就是这个Series。
df.tip[lambda s: max(s.index)] # 获取索引最大值
df[lambda d : d.tip == 2] # tip等于2的所有行
df.[lambda d : d.tip == 2,'tip':] # tip等于2的所有行,tip后所有列
df.loc[:,lambda d: d.columns.str.len()==4] # 列名长度是4的所有列
比较函数
Pandas 提供了一些比较函数,可以将逻辑表达式替换为函数形式
df[df.Q1.eq(60)] # .eq() 等于
# df.ne() # 不等于 !=
# df.le() # 小于等于 <=
# df.lt() # 小于 <
# df.ge() # 大于等于 >=
# df.gt() # 大于 >C
df[df.Q1.ne(80)] # Q1不等于 80
df.loc[df.Q1.gt(90) & df.Q2.lt(90)] # and关系,Q1>90 ,Q2<90
.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')
df.query('Q1 + Q2 > 180')
df.query('Q1 == Q2')
df.query('(Q1<50) & (Q2>40) and (Q3>90)')
df.query('team !="C"')
df.query('team not in ("E","A","B")')
# 如果列名中有空格,可以用反引号
df.query('B == `team name`')
支持使用@符引入变量
a = df.Q1.mean()
df.query('Q1 > @a+40')
df.query('Q1 > `Q2`+@a')
df.eval() 与 df.query() 类似,也可以用于表达式筛选
df[df.eval('Q1 > 90 > Q3 > 10')]
df[df.eval('Q1 > `Q2`+@a')]
筛选 df.filter()
df.filter() 可以对行名和列名进行筛选,支持模糊匹配,正则表达式
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 = pd.DataFrame(data,dtype='float32')
# 对每个字段分别准备
df = pd.read_excel(data,dtype={'team':'string','Q1':'int32'})
推断类型
Pandas可以使用 .infer_objects() 和 convert_dtypes()自动推算数据类型,函数返回一个新的DataFrame,推荐使用convert_dtypes()。
df.convert_dtypes().dtypes # convert_dtypes支持string类型,而infer_objects会把string类型转为Object类型
指定类型
pd.to_XXX系统方法可以将数据安全转换,errors参数可以实现无法转换则转换为兜底类型
m = ['1',2,3]
s = pd.to_numeric(m) # 转成数字
pd.to_datetime(m) # 转成时间
pd.to_timedelta(m) # 转成时间差
pd.to_numeric(m,errors='coerce') # 错误处理
pd.to_numeric(m,errors='ignore') # 错误处理
pd.to_numeric(m,errors='ignore').fillna(0) # 兜底填充
转换为数字类型时,默认返回的dtype是float64还是int64取决于提供的数据,使用downcast参数获得向下转换后的其他类型
pd.to_numeric(m,downcast='integer') # 至少为有符号int数据类型
pd.to_numeric(m,downcast='signed') # 同上
pd.to_numeric(m,downcast='unsigned') # 至少为无符号int数据类型
pd.to_numeric(m,downcast='float') # 至少为有符号float数据类型
可以应用在函数中:
df = df.select_dtypes(include='number')
df.apply(pd.to_numeric) # 应用函数
类型转换astype()
astype() 是最常见也是最通用的数据类型转换方法,一般我们使用astype()操作数据转换就可以
df.Q1.astype('int32').dtypes
# dtype(int32)
df.astype({'Q1':'int32','Q2':'int32'}).dtypes # 指定列转换类型
df.astype('int32') # 所有数据类型转换为int32# rate 中的数据是百分比,转换前先去掉百分号
df.rate.apply(lambda x: x.repalce('%','')).astype('float')/100
转为时间类型
通常使用pd.to_datetime和s.astype(‘datetime64[ns]’)来做时间类型转换
t = pd.Series(['20200801','20200802'])
pd.to_datetime(t)
# 0 2020-08-01
# 1 2020-08-02
# dtype: datetime64[ns]t.astype('datetime64[ns]')
# 0 2020-08-01
# 1 2020-08-02
# dtype: datetime64[ns]
数据排序
索引排序
df.sort_index()实现按索引排序,默认以小到大的升序方式排序。传入ascending=False参数,按照降序排序
df.sort_index(ascending=False)
按列索引排序:
# axis=1 在列索引方向上排序
df.sort_index(axis=1,ascending=False) # 列降序排列
更多方法:
s.sort_index(inplace=True) # 排序后生效,改变原数据
s.sort_index(ignore_index=True) # 索引重新0-(n-1)排,很有用,可以得到它的排序号
s.sort_index(na_position='first') # 空值在前,另外'last'表示空值在后
s.sort_index(level=1) # 如果是多层,排列一级(层级从0开始)
s.sort_index(level=1,sort_remaining=False) # 这层不排
df.sort_index(axis=1) # 行索引排序,表头排序;会把列按列名顺序排序
df.reindex()指定自己定义顺序的索引,实现行和列的顺序重新定义
df = pd.DataFrame({'A':[1,2,3],'B':[3,5,6]
},index = ['a','b','c'])
df.reindex(['c','b','a']) # 要求重新指定索引顺序
df.reindex(['B','A'],axis=1) # 指定列顺序
数值排序
数据值的排序主要使用sort_values(),数字按照大小顺序,字符按照字母顺序。
df.Q1.sort_values() # Series 排序,返回 Series
df.sort_values('Q4') # DataFrame 排序,返回DataFrame# 默认是升序,可以指定排序方式
df.sort_values(by=['team','name'],ascending=[True,False]) #team升序,name降序
其他常用方法
s.sort_values(ascending=False) # 降序
s.sort_values(inplace=True) #修改生效
# df按指定字段排序
df.sort_values(by=['team'])
df.sort_values('Q1')
# 按多个字段,先排team,在同team内再排Q1
df.sort_values(by=['team','Q1'])
df.sort_values(by=['team','Q1'],ascending=False) # 全降序
df.sort_values(by=['team','Q1'],ascending=[True,False]) # 指定team升,Q1降
df.sort_values('team',ignore_index=True) # 索引重新0-(n-1)排
混合排序
有时需要用索引和数据值混合排序
df.set_index('name',inplace=True) # 设置name为索引
df.index.names=['s_name'] # 给索引起个名字
df.sort_values(by=['s_name','team']) # 排序 ,先按team排序,再按索引排序
df.set_index('name').sort_values('team').sort_index() # 效果同上
还可以使用df.reindex(),通过给定新的索引方式来排序
df.reindex(df.name.sort_values().index)
按值大小排序
nsmallest()和nlargest()用来实现数字的排序,并可以指定返回的个数
df.nsmallest(5,['Q1','Q2']) # 先按Q1最小在前,如果相同,Q2小的在前s.nsmallest(3) # 最小的3个
s.nlargest(3) # 最大的3个
#指定列
df.nlargest(3,'Q1')
df.nlargest(5,['Q1','Q2'])