目录
进阶操作
复杂查询
逻辑运算
df.Q1 > 36
df.index == 1
df.loc[:,'Q1':'Q4'] > 60
#Pandas支持很多逻辑运算,这里不再介绍
函数筛选
# 可以在表达式处使用lambda函数
df.Q1[lambda s: max(s.index)] #查询最大的索引值
lambda 形式参数:函数表达式
比较函数
pandas提供了一些比较函数,使我们可以将逻辑表达式替换为函数形式
df.eq() #等于
df.ne() #不等于
df.le() #小于等于
df.lt() #小于
df.ge() #大于等于
df.gt() #大于
df.query()查询
df.query(expr) #使用布尔表达式查询df的列
#举例
df.query('Q1>Q2>90')
df.query('Q1+Q2>180')
df.query('Q1==Q2')
df.query('(Q1<50) & (Q2>40) and (Q3>90)')
#支持使用@符号引入变量
a = df.Q1.mean()
df.query('Q1 > @a+40')
df.eval() #与.query()类似
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的行
df.filter(regex='^2',axis=0).filter(like='Q',axis=1)
按数据类型查询
df.select_dtypes(include=None, exclude=None)
include: 'float64' \ 'bool' \ 'number'
exclude: 同上
数据类型转换
#推断类型
df.infer_objects() #自动转换合适的数据类型
df.convert_dtypes() #自动转换,支持str类型
#指定类型
pd.to_XXX()
pd.to_numeric(,downcast='integer')#转为数字,且是int,而非float
#downcast:integer\signed\unsigned\float
pd.to_datetime(,errors='ignore')#转为时间
pf.to_datetime(,format='%Y-%m-%d')
pd.to_timedelta(,errors='coerce')#转为时间差
pd.to_datatime(df[['year','month','day']])#组合成日期
#类型转换astype()
df.column.astype('int32')
df.astype({'Q1':'int32','Q2':'int32'})
#当数据的格式不具备转换为目标类型的条件时,需要先对数据进行处理。
#例如:80%
data.rate.apply(lambda x: x.replace('%','')).astype('float')/100
转换为时间类型
这里我想拿出来单独做笔记,因为我经常被时间类型是比较弄的焦头烂额。
pd.to_datatime()
s.astype('datatime64[ns]')
例:
t = pd.Series(['202000101','20001103'])
以上这些当转换格式挺好用,但如果筛选时间段,我建议还是用str类型,正则表达式比较好用,例如:
#筛选2000年以后的数据
data_20 = data[data.filter(regex='^20',ax=0)]
#正则表达式什么时候用查百度就行
数据排序
#索引排序
df.sort_index()
df.sort_index(ascending=False) #倒序
df.sort_index(axis=1) #列索引
df.sort_index(inplace=True) #改变原数据
df.sort_index(ignore_index=True) #重新建立索引
df.sort_index(na_position='first') #空值在前'last'
df.reindex() #指定自己定义顺序的索引
#数值排序
df.sort_values()
df.sort_values(by= ,ascending= ) #上面的参数也都有效
#按大小值排序
df.nsmallest(5, []) #按[]中列名排序,显示最小的5行数据
df.nlargest()
添加修改
.replace.fillna.rename.set_axis.insert.assign.eval.append.concat.dropna
#替换数据
df.replace(0,5) #0换5
df.replace([0,1,2],3) #012换3
df.replace([0,1,2],[3,4,5]) #对应替换
s.replace([1,2],method='bfill')#下一位作为填充
#method:pad(上下均值)\ffill\bfill
df.replace({}) #字典对应替换
df.replace({'Q1':1},100) #将Q1中的值1换为100
df.repalce({'Q1':{1:10,2:20}})#指定Q1列中的值1、2换为10、20
#正则表达式
df.replace(to_replace=r'',value='new',regex=True)
df.replace({'Q1':r''},{'Q1':'new'},regex=True)
df.replace(regex={r'':'new' 'foo':'xyz'})
df.replace(regex=[r'', 'foo'],value='new')
#填充空值
df.fillna(0) #全部填充为0
#method: backfill\bfill\pad\ffill\None
values = {'A':0,'B':1}
df.fillna(value=values) #为各列按字典填充不同的值
df.fillna(value=values,limit=1)#只替换第一个
#修改索引名
df.rename(columns={'team':'class'})
df.rename(index=str) #d对类型进行修改
df.rename(str.lower,axis='columns')#传索引类型
df.rename_axis('animal')
#可以用set_axis进行修改设置
df.set_axis(['a', 'b', 'c'], axis=0)
#增加列
#把所有为数字的值相加
df['total']=df.select_dtypes(include=['int'].sum(1))
df['total']=df.loc[:,'Q1':'Q4'].apply(lambda x:sum(x),axis='columns')
#插入列
df.insert(loc,column,value)
#loc:插入位置,+1就是第几列
#column:列名,value:列值
#已存在相同列会报错,allow_duplicates=True插入一个同名的列
#指定列
df.assign(k=v) #指定一个新列,k为列名,v为值,v必须是一个与原数据同索引的series
df.assign(total=df.sum(1))
#增加两列
df.assign(total=df.sum(1).assign(Q=100))#增加了total和Q列而已
#链式方法
{
df.assign(total=df.sum(1))
.assign(Q=100)
.assign(name_len=df.name.str.len())
}
#执行表达式
df.eval('k=v') #可以以字符形式传入表达式,增加列数据
#增加行
df.loc[100]=['','', , ] #给新增第一百行加数据
df.loc[101]={'Q1':88,'Q2':99}#指定列加数据,无为NA
#追加合并
df1.append(df2)
pd.concat( #增加一个一层索引key取名Series name,变多层索引
[s1,s2],
keys=['s1','s2'],
names=['Series name','Row ID'])
'''
Series name Row ID
s1 0 1
1 2
s2 0 a
1 b
'''
pd.concat(
[df1,df2],
sort=False,
join="inner", #只连相同列
axis=1) #连接列
#删除
df.pop()
#删除空值
df.dropna() #一行中有一个缺失值就删除
df.dropna(
axis='columns',
how='all', #全部值为NA才删除
thresh=2, #至少有两个空值时才删除
inplace=True)
高级过滤
.select_dtypes.where\np.where.mask.lookup
df.select_dtypes(includ='number')
df.where(df>70) #符合条件的保留,其他填充为NA
df.Q1.where(pd.Series([True]*3))#前三个原值,其他为NA
df.where(df>=60,'不及格') #可以指定一个值替换NAN
c = df%2==0
df.where(~c,-(df-20))
#np.where()对满足条件的值进行修改
np.where(df>=60,'合格','不合格')#返回的是一个二维array
#让条件为假,从而应用np.where的计算结果
df.where(df==999999,np.where(df>60,'合格','不合格'))
{
df.assign(avg=mean(1))
.assign(及格=lambda d:np.where(d.avg>=60,'是','否'))
}
#df.mask()用法与df.where()基本相同
df.mask(s>80) #将满足位置填充为NA
#df.lookup(行标签,列标签) #返回一个array,查看
df.lookup([1,3,4],['Q1','Q2'])
数据迭代
.zip.interrows.itertuples.item
df.name.values返回array结构可用于迭代
#迭代指定的列
for i in df.name:
print(i)
#迭代索引和指定的两列,zip用于打包
for i,n,q in zip(df.index, df.name, df.Q1)
print(i,n,q)
#df.iterrows(),将df由(索引,行数据)组成Series对象进行迭代
for index, row in df.interrows():
print(index,row['name'],row.Q1)
#df.itertuples(),生成一个namedtuples类型数据,更快
for row in df.itertuples():
print(row)
'''
Pandas(Index=0,Q1=89,Q2=21)
Pandas(Index=1,Q1=57,Q2=60)
'''
df.itertuples(
index=False, #不包含索引数据
name='') #自定义name,就是把Pandas替换
#df.items(),返回一个(列名,本列的Series结构数据)
'''输出所有列
Q1
0 12
1 15
Name:Q1,dtype:int64
Q2
0 48
1 66
Name:Q2,dtype:int64
'''
#按列迭代
for column in df:
print(column)
函数应用
pip()/apply()/applymap()/map()
#pipe()管道方法
#它可以让我们写的分析过程标准化、流水线化,
#达到复用目标,它也是最近非常流行的链式方法的重要代表。
df.pipe(<函数名>,<传给函数的参数列表或字典>)
#对df多重应用多个函数
f(g(h(df), arg1=a), arg2=b, arg3=c)
#用pipe可以把它们连接起来
(
df.pipe(h)
.pipe(g, arg1=a)
.pipe(f, arg2=b, arg3=c)
)
#将'arg2'参数传给函数f,然后作为函数整体接受后面的参数
(
df.pipe(h)
.pipe(g,arg1=a)
.pipe((f,'arg2'),arg1=a,arg3=c)
)
#df_,使用前数据本身
df.pipe(lambda df_,x,y: df_[(df_.Q1>=x)&(df_.Q2>=y)],80,90)
#筛选处Q1大于等于80且Q2大于等于90的数据
#apply()
#apply()可以对df按行和列进行函数处理,series传入具体值
#判断一个值是否在另一个类似列表的列中
df.apply(lambda d: d.s in d.s_list,axis=1)#布尔序列
df.apply(lambda d: d.s in d.s_list,axis=1).astype(int)#0\1序列
#经常配合np.where()使用
fun = lambda x:np.where(x.team=='A' and x.Q1>90, 'good','other')
df.apply(fun,axis=1)
#其他写法
(
df.apply(lambda x:x.team=='A' and x.Q1>90, axis=1)
.map({True:'good', False:'other'})
)
df.apply(lambda x:'good' if x.team=='A' and x.Q1>90 else '',axis=1)
df.apply(fun) #自定义
df.apply(max) #内置函数,pandas自己的函数
df.apply(lambda) #匿名函数
df.apply(np.mean) #其他库的函数
#applymap()元素级函数应用
df.applymap(参数为单个数据的函数)
#map(),输入对应关系映射值返回最终数据
df.team.map('I am {}'.format, na_action='ignore')
#agg()使用指定轴上的一项或多项操作进行汇总
df.agg('max') #每列的最大值
df.agg(['sum','min']) #将所有列聚合产生sum和min两行
df.agg({'Q1':['sum','min'],'Q2':['min','max']})#序列多个聚合
#分组后聚合
df.groupby('team').agg('max')
df.Q1.agg(['sum','mean'])
#每列使用不同方法进行聚合
df.agg(
a=('Q1',max),
b=('Q2',min))
df.loc[:,'Q1':].agg(pd.Series.add, other=10)
#transform()返回的是原数据的结构
df.transform(lambda x: x*2) #应用匿名函数
df.transform([np.sqrt, np.exp]) #调用多个函数
df.transform({'A': np.abs, 'B': lambda x: x+1})
#copy()返回一个新对象,且与原对象没有关系deep=T是默认
df_copy = df.copy()
参考内容:《深入浅出Pandas》