通过 SQL 查询学习 Pandas 数据处理
Pandas 是一款广泛使用的数据处理工具。结合 NumPy 和 Matplotlib 类库,我们可以在内存中进行高性能的数据清洗、转换、分析及可视化工作。虽然 Python 本身是一门非常容易学习的语言,但要熟练掌握 Pandas 丰富的 API 接口及正确的使用方式,还是需要投入一定时间的。
对于数据开发工程师或分析师而言,SQL 语言是标准的数据查询工具。本文提供了一系列的示例,如何将常见的 SQL 查询语句使用 Pandas 来实现。
Pandas 的安装和基本概念并不在本文讲述范围内,请读者到官网上阅读相关文档,或者阅读《利用 Python 进行数据分析》一书。我推荐大家使用 Anaconda Python 套件,其中集成了 Spyder 集成开发环境。在运行下文的代码之前,请先引入 Pandas 和 NumPy 包:
import pandas as pd
import numpy as np
FROM
- 读取数据
首先,我们需要将数据加载到工作区(内存)。Pandas 原生支持非常多的数据格式,CSV 是较常见的一种。我们以航班延误时间数据集为例(下载地址):
date,delay,distance,origin,destination
02221605,3,358,BUR,SMF
01022100,-5,239,HOU,DAL
03210808,6,288,BWI,ALB
我们可以使用 pd.read_csv
函数加载它:
df = pd.read_csv('flights.csv', dtype={'date': str})
df.head()
这条命令会将 flights.csv
文件读入内存,使用首行作为列名,并自动检测每一列的数据类型。其中,由于 date
一列的日期格式是 %m%d%H%M
,自动转换成数字后会失去月份的前异零(02 月的 0),因此我们显式指定了该列的 dtype
,告知 Pandas 保留原值。
df.head
用于查看数据集的前 N 行,功能类似于 LIMIT N
。如果要实现 LIMIT 10, 100
,可以使用 df.iloc[10:100]
。此外,IPython 终端默认只显示 60 行数据,我们可以通过以下方法修改设置:
pd.options.display.max_rows = 100
df.iloc[10:100]
另外一种常见的数据源是关系型数据库,Pandas 也提供了内置支持:
conn = pymysql.connect(host='localhost', user='root')
df = pd.read_sql("""
select `date`, `delay`, `distance`, `origin`, `destination`
from flights limit 1000
""", conn)
如果要将 DataFrame 保存到文件或数据库中去,可以分别使用 pd.to_csv
和 pd.to_sql
函数。
SELECT
- 选择列
SELECT
语句在 SQL 中用于选择需要的列,并对数据做清洗和转换。
df['date']
df[['date', 'delay']]
df.loc[10:100, ['date', 'delay']]
SQL 提供了诸多函数,大部分都可以用 Pandas 来实现,而且我们也很容易用 Python 编写自定义函数。下面我将列举一些常用的函数。
字符串函数
Pandas 的字符串函数可以通过 DateFrame 和 Series 的 str
属性来调用,如 df['origin'].str.lower()
。
df['origin'].str.cat(df['destination'], sep=' to ')
df['origin'].str.strip()
df['origin'].str.len()
df['origin'].str.replace('a', 'b')
df['origin'].str[0:1]
df['domain'].str.split('.').str[:2].str.join('.')
df['domain'].str.extract(r'^([^.]+.[^.]+)')
Pandas 有一个名为广播的特性(broadcast),简单来说就是能够将低维数据(包括单个标量)和高维数据进行结合和处理。例如:
df['full_date'] = '2001' + df['date']
df['delay'] / 60
df['delay'].div(60)
Pandas 还内置了很多字符串函数,它们的用法和 SQL 有一定区别,但功能更强。完整列表可以参考文档 Working with Text Data。
日期函数
pd.to_datetime
用于将各种日期字符串转换成标准的 datetime64
类型。日期类型的 Series 都会有一个 dt
属性,从中可以获取到有关日期时间的信息,具体请参考文档 Time Series / Date functionality。
df['datetime'] = pd.to_datetime(df['full_date'], format='%Y%m%d%H%M%S')
df['datetime'].dt.strftime('%Y-%m-%d')
df['datetime'].dt.month
df['datetime'].dt.hour
df['datetime'].view('int64') // pd.Timedelta(1, unit='s').value
pd.to_datetime(df['timestamp'], unit='s')
df['datetime'] + pd.Timedelta(1, unit='D')
WHERE
- 选择行
在 Pandas 中使用逻辑表达式后,会返回一个布尔型的 Series,通过它可以对数据集进行过滤:
(df['delay'] > 0).head()
df[df['delay'] > 0]
我们可以用位运算符来组合多个查询条件:
df[(df['delay'] > 0) & (df['distance'] < = 500)]
df[(df['delay'] > 0) | (df['origin'] == 'BUR')]
df[~(df['delay'] > 0)]
对于 IS NULL
和 IS NOT NULL
,也提供了相应的内置函数:
df[df['delay'].isnull()]
df[df['delay'].notnull()]
此外,Pandas 还提供了 df.query
方法,可以使用字符串表达式来编写过滤条件:
df.query('delay > 0 and distaince < = 500')
df.query('(delay > 0) | (origin == "BUR")')
其实,Pandas 提供了功能强大的数据选取工具,很多是无法用 SQL 表达出来的,建议详细阅读 Indexing and Selecting Data 文档,其中包含了丰富的示例。
GROUP BY
- 汇总
df.groupby('origin').size()
聚合运算包含了两个部分,一是分组字段,二是聚合函数。我们可以传递多个分组字段给 df.groupby
,也能够指定多个聚合函数:
df.groupby(['origin', 'destination']).agg({
'delay': np.sum,
'distance': np.mean
})
df.groupby('origin')['delay'].agg(['min', 'max'])
我们还可以将函数的运行结果作为分组条件。更多示例请见 Group By: split-apply-combine。
df.set_index('origin').groupby(len).size()
ORDER BY
- 排序
Pandas 中有两类排序,按索引和按数值。如果不了解 Pandas 的索引,还请自行查阅相关教程。
df.set_index('origin').sort_index()
df.sort_values(by='origin')
df.sort_values(by=['origin', 'destination'], ascending=[True, False])
JOIN
- 关联查询
pd.merge(df_product, df_category, left_on='cid', right_on='id', how='left')
如果联合查询的键是同名的,可以直接使用 on=['k1', 'k2']
。默认的关联方式是 INNER JOIN
( how='inner'
),其它还有左外连接( left
)、右外连接( right
)、以及 FULL OUTER JOIN
( outer
)。
pd.concat
可用于实现 UNION
查询。 更多关联查询的示例请参考 Merge, join, and concatenate。
pd.concat([df_a, df_b]).drop_duplicates()
最后,我们经常会需要在分组中按某种规则排序,并获得前几位的记录。MySQL 中需要通过变量来实现,Pandas 中则可以使用 rank
函数:
rnk = df.groupby('origin')['delay'].rank(method='first', ascending=False)
df.assign(rnk=rnk).query('rnk < = 3').sort_values(['origin', 'rnk'])
作者:张吉
来源:http://shzhangji.com/cnblogs/2017/07/23/learn-pandas-from-a-sql-perspective/
编辑 | 码哥
图片源于网络,版权归原作者所有
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
随时掌握互联网精彩
- 1 习近平拉美之行的三个“一” 7979119
- 2 山里藏价值6000亿元黄金?村民发声 7997983
- 3 微信或史诗级“瘦身” 内存有救了 7888844
- 4 中国主张成为G20峰会的一抹亮色 7787536
- 5 朝鲜将军队提升至战斗准备状态 7671441
- 6 男子求助如何打开亡父遗留14年手机 7535826
- 7 浙大贫困生晒旅游照 民政局回应 7460851
- 8 黄晓明新片上映一周票房仅400万 7370624
- 9 男子抱3个小孩跳海?官方通报 7272692
- 10 千年古镇“因网而变、因数而兴” 7185702