数据处理03:Python数据分析库Pandas

Pandas 是最强大的 Python 数据分析库,它在 NumPy 基础之上构建,功能完善、性能出色并且操作便捷。项目官网 http://pandas.pydata.org/

03_pandas.png

Pandas 已包含于 Anaconda 中,导入模块时请按惯例命名为 pd:

In [1]: import pandas as pd

In [2]: pd.__version__  # 查看版本号
Out[2]: '0.24.1'

Pandas 所提供的对象类型主要有“数据系列”(Series)和“数据网格”(DataFrame)——Series 像是一维数组而 DataFrame 像是二维数组,与数组的关键区别在于它们包含可自定义的“数据索引”(Index),类似于字典的键。DataFrame 中的列就是 Series 对象,每一列有各自的数据类型但共享相同的 Index。让我们先调用构造器创建一个 Series:

In [3]: pd.Series(["北京", "上海", "广州", "深圳"])
Out[3]: 
0    北京
1    上海
2    广州
3    深圳
dtype: object

In [4]: Out[3].index  # index属性指向索引
Out[4]: RangeIndex(start=0, stop=4, step=1)

In [5]: cityname = pd.Series(["北京", "上海", "广州", "深圳"], index=["bj", "sh", "gz", "sz"])

In [6]: cityname.index
Out[6]: Index(['bj', 'sh', 'gz', 'sz'], dtype='object')

新的 Series 使用城市名拼音缩写作为自定义索引,但要注意的是默认的序列索引仍然有效:前者称为显式索引而后者称为隐式索引,当以整数作为显式索引时这可能会引发混淆,因此你还可以用“定位器”属性 loc 和 iloc 来明确指定索引方式:

In [7]: cityname["sz"]
Out[7]: '深圳'

In [8]: cityname[-1]
Out[8]: '深圳'

In [9]: cityname.loc["bj"]
Out[9]: '北京'

In [10]: cityname.iloc[0]
Out[10]: '北京'

下面让我们再尝试创建 DataFrame,所用方式是向构造器传入一个由可索引对象组成的字典,所生成 DataFrame 的列数据和列标签就是字典的值和键,行索引是一个由所有列数据共用的 Index,列索引则是一个由所有列标签组成的 Index:

In [11]: citypop = {"bj": 1877.7, "sh": 2115, "gz": 1246.83, "sz": 1137.89}

In [12]: df = pd.DataFrame({"名称": cityname, "人口": citypop})

In [13]: df
Out[13]: 
    名称       人口
bj  北京  1877.70
gz  广州  1246.83
sh  上海  2115.00
sz  深圳  1137.89

In [14]: df.index  # index属性指向行索引
Out[14]: Index(['bj', 'gz', 'sh', 'sz'], dtype='object')

In [15]: df.columns  # columns属性指向列索引
Out[15]: Index(['名称', '人口'], dtype='object')

你可以使用 Series 与 DataFrame 的索引、属性或方法,以及模块的函数对数据执行各种操作,包括读取、更新和运算等等——注意方法和函数默认会返回新对象而非原地修改:

In [16]: df["名称"]  # 以索引方式获取列
Out[16]: 
bj    北京
gz    广州
sh    上海
sz    深圳
Name: 名称, dtype: object

In [17]: df.人口  # 以属性方式获取以标识符规则命名的列
Out[17]: 
bj    1877.70
gz    1246.83
sh    2115.00
sz    1137.89
Name: 人口, dtype: float64

In [18]: df.iloc[2:]  # 以序列索引方式获取行
Out[18]: 
    名称       人口
sh  上海  2115.00
sz  深圳  1137.89

In [19]: df["人口"].sum()  # 列数据求和
Out[19]: 6377.42

In [20]: df.sort_values("人口", ascending=False)  # 按人口列降序排列
Out[20]: 
    名称       人口
sh  上海  2115.00
bj  北京  1877.70
gz  广州  1246.83
sz  深圳  1137.89

In [21]: df["区号"] = ["010", "020", "021", "0755"]  # 添加新列
    ...: df
Out[21]: 
    名称       人口    区号
bj  北京  1877.70   010
gz  广州  1246.83   020
sh  上海  2115.00   021
sz  深圳  1137.89  0755

In [22]: df.loc['tj'] = ['天津', 875.24, '022']  # 添加新行
    ...: df
Out[22]: 
    名称       人口    区号
bj  北京  1877.70   010
gz  广州  1246.83   020
sh  上海  2115.00   021
sz  深圳  1137.89  0755
tj  天津   875.24   022

In [23]: df[df.人口 >= 1000]  # 按条件筛选
Out[23]: 
    名称       人口    区号
bj  北京  1877.70   010
gz  广州  1246.83   020
sh  上海  2115.00   021
sz  深圳  1137.89  0755

In [24]: df.人口 >= 1000  # 筛选的原理是用布尔值系列来索引
Out[24]: 
bj     True
gz     True
sh     True
sz     True
tj    False
Name: 人口, dtype: bool

In [25]: df2 = pd.DataFrame([['重庆', 851.8, '023'], ['南京', 617.82, '025']], columns=["名称", "人口", "区号"], index=["cq", "nj"])
    ...: pd.concat([df, df2])  # 拼接两个 DataFrame
Out[25]: 
    名称       人口    区号
bj  北京  1877.70   010
gz  广州  1246.83   020
sh  上海  2115.00   021
sz  深圳  1137.89  0755
tj  天津   875.24   022
cq  重庆   851.80   023
nj  南京   617.82   025

接下来的例子是对中国历史上皇帝们的寿命进行统计分析,这次使用现成数据来生成 DataFrame。Pandas 支持读取多种类型的资源,例如以逗号作为分隔符的文本格式(CSV):

# 短网址对应的原文件
# https://gitee.com/freesand/pyStudy/raw/master/data/emperor.csv
df = pd.read_csv("http://t.cn/EMl0NtB")

对于大尺寸 DataFrame,推荐先用 shape 和 dtypes 属性查看形状和列数据类型,也可用 head() 方法预览前 5 行内容,DataFrame 在 Jupyter Notebook 中会以表格形式输出:

print("数据网格形状:", df.shape)
print("各列数据类型:")
print(df.dtypes)
df.head()
03_pandas_emperor.png

对于已生成的 DataFrame,还可以进行一些调整操作(修改列标签、去除多余内容等)再开始数据分析,例如列出寿命达到 80 岁的皇帝:

df.columns = ["序号", "名号", "寿命", "生卒", "朝代"]
df[df.寿命 >= 80]
03_pandas_filter.png

筛选出明清两朝的皇帝:

mingqing = df[df.朝代.isin(["明", "清"])]
mingqing.head()
03_pandas_mingqing.png

比较明清两朝的皇帝寿命——聚合输出分组总计数、最低值、最高值、平均值、中位数:

compare = mingqing.groupby("朝代").寿命.agg(["count", "min", "max", "mean", "median"])
compare
03_pandas_mingqingcomp.png

还可以根据全体皇帝的寿命数据绘制直方图来显示值的分布:

import matplotlib.pyplot as plt
plt.style.use("seaborn")
plt.hist(df.寿命, range=(0, 100))  # 直方图,范围0至100(默认为最小值到最大值)
03_pandas_pyplot.png

Pandas 的功能非常丰富,想更深入地了解请查看官方文档 http://pandas.pydata.org/pandas-docs/stable/

——编程原来是这样……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容