编程原来是这样程序猿阵线联盟-汇总各类技术干货

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

2019-03-15  本文已影响22人  starglow_leo

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/

——编程原来是这样……

上一篇下一篇

猜你喜欢

热点阅读