前言
pandas的DataFrame是类似于一张表的结构,但是并没有像数据库表那样的SQL操作。虽然如此,它依然可以使用python语言的风格实现SQL中的所有操作。
文章较长,建议点击右侧目录定位到自己感兴趣的章节进行重点阅读。
微信公众号:大数据报文
where、limit、sort by和order by
首先我们讲一些常用的最基本的SQL操作。,首先创建一个DataFrame。
# 首先构建一个df,用于执行相关操作
import numpy as np
import pandas as pd
index = pd.date_range('20191201',periods=30)
df = pd.DataFrame(np.random.randn(30,7),index=index,columns=['Sun','Mon','Tues','Wed','Thur','Fri','Set'])
# 查询df表中,12月前五天工作日的所有数据
# sql:select Mon, Tues, Wed, Thur, Fri from df limit 5;
# pandas DataFrame方式
df[['Mon','Tues','Wed','Thur','Fri']].head() # 默认取前5
'''
Mon Tues Wed Thur Fri
2019-12-01 0.804610 0.368983 -0.601083 -1.245074 -0.484798
2019-12-02 1.260151 -1.409303 -0.634084 -1.036428 2.090475
2019-12-03 -1.728074 0.906895 0.015032 -1.311078 -1.329503
2019-12-04 -0.489368 -1.285120 -0.115737 0.138407 -1.360219
2019-12-05 -0.686239 -0.715345 -1.216979 -0.110652 -0.716998
'''
# 使用where条件,过滤大于Mon大于1的行,并且是工作日的列,并按照Mon降序排序,去除前五行
# SQL:select Mon,Tues,Wed,Thur,Fri from df where Mon > 0 order by Mon desc limit 5;
df[df['Mon'] > 1][['Mon','Tues','Wed','Thur','Fri']].sort_values('Mon',ascending=False).head()
'''
Mon Tues Wed Thur Fri
2019-12-24 3.428393 -0.117491 -1.050417 0.013496 0.744957
2019-12-22 2.264095 0.580407 1.992808 0.277741 0.691637
2019-12-18 1.919169 1.108332 1.135021 0.468483 0.718493
2019-12-29 1.442418 -0.555409 1.483127 -0.322987 0.480643
2019-12-11 1.304989 0.289543 0.591583 -0.420857 -0.407957
'''
where多条件查询
and条件
# where中有多个条件,要注意两个条件如果是and用&,且条件要用小括号包裹一下
# select * from df where Sun > 0 and Mon < 0 order by Sun desc;
df[(df['Sun'] > 0) & (df['Mon'] < 0)].sort_values('Sun',ascending=False)
'''
Sun Mon Tues Wed Thur Fri Set
2019-12-04 2.196878 -0.489368 -1.285120 -0.115737 0.138407 -1.360219 0.093402
2019-12-25 1.245318 -2.336478 0.166749 0.665577 -1.740905 -0.719664 0.011632
2019-12-21 0.984376 -0.395367 0.859675 0.035257 -0.326325 2.049639 -0.104049
2019-12-20 0.916271 -2.208159 0.680670 -1.392549 0.310099 -0.655601 1.008948
2019-12-08 0.680180 -0.682509 0.263885 0.270527 0.428712 -0.566694 -0.426841
2019-12-03 0.552253 -1.728074 0.906895 0.015032 -1.311078 -1.329503 -1.179729
'''
or条件
# or条件,在DataFrame中使用的是按位或符号:|
# sql: select * from df where Sun > 1 or Set > 1 order by Sun;
df[(df['Sun'] > 1) | (df['Set'] >1)].sort_values('Sun',ascending=False)
'''
Sun Mon Tues Wed Thur Fri Set
2019-12-19 2.200183 1.126807 1.650156 0.165897 1.262572 1.083929 2.151953
2019-12-04 2.196878 -0.489368 -1.285120 -0.115737 0.138407 -1.360219 0.093402
2019-12-25 1.245318 -2.336478 0.166749 0.665577 -1.740905 -0.719664 0.011632
2019-12-07 1.189126 0.115880 0.237899 -0.265956 0.882976 -0.932736 0.385194
2019-12-20 0.916271 -2.208159 0.680670 -1.392549 0.310099 -0.655601 1.008948
2019-12-14 0.063325 0.553131 0.221180 0.265838 0.260798 1.100413 1.112681
'''
空值查询
在DataFrame中判断空值使用isna()和notna()两个方法
# 先构造一个带空置的DataFrame
dfna = pd.DataFrame({
"one":pd.Series([1,2,3,np.NaN,5,6]),
"two":pd.Series([1,2,np.NaN,5,6,np.NaN]),
"three":pd.Series([np.NaN,5,6,np.NaN,7,8]),
})
# 查询three列不是空值的全部数据
# SQL:select * from dfna where three is not null;
dfna[dfna['three'].notna()]
'''
one two three
1 2.0 2.0 5.0
2 3.0 NaN 6.0
4 5.0 6.0 7.0
5 6.0 NaN 8.0
'''
# 查询表中three是空值的全部列
# SQL:select * from dfna where three is null;
dfna[dfna['three'].isna()]
'''
one two three
0 1.0 1.0 NaN
3 NaN 5.0 NaN
'''
分组
-
先创建一个表,用于分组测试用
-
DataFrame的分组与SQL最大的不同时,SQL只能对分组列进行聚合,但是DataFrame不止可以对分组列聚合,其他列只要可以进行聚合操作都可以进行聚合
-
DataFrame可以对多列进行不同类型的聚合运算,需要使用agg函数并传入一个dict对象
-
可以使用多列作为条件进行分组
# 人员基本信息表
fdf = pd.DataFrame({
"name":pd.Series(['Zero','Zoey','Bella','Kat','Sid']),
"age":pd.Series([23,24,23,26,23]),
"gender":pd.Series(['male','female','female','female','male']),
"address":pd.Series(['jinan','nanjing','qingdao','dongjing','dongjing']),
"salary":pd.Series([8888.8,6666.6,1234.5,2345.6,5678.9])
})
# 按性别分组,求出男女的平均工资
fdf.groupby('gender').mean()['salary']
'''
gender
female 3415.566667
male 7283.850000
Name: salary, dtype: float64
'''
#求出男女人数
fdf.groupby('gender').size()
'''
gender
female 3
male 2
dtype: int64
'''
# 分组后对不同列进行不同类型的聚合
# 按照gender进行分组,对salary求平均值,对age求总数
fdf.groupby('gender').agg({'salary':np.mean, 'age':np.size})
'''
salary age
gender
female 3415.566667 3
male 7283.850000 2
'''
JOIN
-
join跟sql一样支持左外、右外,全外和内连接四种连接
-
先创建两个df用于进行join操作
-
DataFrame可以使用join()和merge()两种函数进行join操作,这里使用merge进行测试
# 创建两个待join的表
df1 = pd.DataFrame({
"key":['A','B','C','D','E'],
"val":np.random.randn(5)
})
df2 = pd.DataFrame({
"key":['C','B','F','H','D'],
"val":pd.Series(np.random.randn(5))
})
# 根据key列进行join操作,内连接
df1.merge(df2,on='key')
# 右外连接
df1.merge(df2, on='key', how='right')
# 左外连接
df1.merge(df2, on='key', how='left')
# 全外连接
df2.merge(df2, on='key', how='outer')
# 全外,上面的全外不是真的全外,要用这种方式才能做到全外连接
pd.merge(df1, df2, on='key',how='outer')
Union
-
union操作使用concat()进行完成
-
concat是pandas的函数笔试dataframe的函数
-
concat接受一个数组作为入参,所以在进行union的时候,需要将多个df放入一个数组中
# 合并两个DataFrame并去重
pd.concat([df1, df2]).drop_duplicates()
'''
key val
0 A -0.309694
1 B 1.455732
2 C 0.436620
3 D 0.970044
4 E -0.689002
0 C 0.405784
1 B -0.522076
2 F 0.147848
3 H -1.609153
4 D 1.205187
'''
添加一列
df1.assign(score=np.random.randint(60,100,size=5))
'''
key val score
0 A -0.309694 80
1 B 1.455732 92
2 C 0.436620 92
3 D 0.970044 95
4 E -0.689002 89
'''
top N 相关函数
-
在DataFrame中有直接求top N的函数
-
nlargest(n,col)求col列中前n大的行
-
nsmallest(n,col)求col列中前n小的行
df.nlargest(3,columns='Sun')
df.nsmallest(3,columns='Sun')
# 这里也是top N,但是是基于分组的top N
# assign是添加一列
# 添加的列叫rn
# sort_values是对salary进行排序
# groupby是对gender进行分组
# cumcount是按照上面给定的顺序从0开始给一个顺序号
fdf.assign(
rn=fdf.sort_values(['salary'], ascending=False)
.groupby(['gender'])
.cumcount()+1
).sort_values('name')
# 下面的结果说明了男女中工资从低到高的排序顺序
'''
name age gender address salary rn
2 Bella 23 female qingdao 1234.5 3
3 Kat 26 female dongjing 2345.6 2
4 Sid 23 male dongjing 5678.9 2
0 Zero 23 male jinan 8888.8 1
1 Zoey 24 female nanjing 6666.6 1
'''
总结
pandas是一个非常强大的科学计算库,DataFrame的功能也远不止这么简单。这里只是总结了一些常用的类似于SQL的操作方法。如果需要更加复杂的功能可以查看DataFrame的官方文档。