pandas简单介绍和本文说明
pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。
pandas is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool,built on top of the Python programming language.
进入官网可以看到现在最新的版本是1.0.3,之后代码也就使用1.0.3的pd咯。此系列主要参考Pandas官方文档和由Datawhale主办的一期Joyful-Pandas,结合自己使用pandas的一些体会进行扩展,最后还有个人对问题和练习的解答。使用到的数据集可以在此下载。
#从清华镜像拉装1.0.3版本的Pandas
!pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas==1.0.3
import pandas as pd
#查看Pandas版本
pd.__version__
'1.0.3'
df = pd.read_csv('work/table.csv',index_col='ID')
df.head()
一、SAC过程
SAC指的是分组操作中的split-apply-combine过程
在该过程中,我们实际往往会遇到四类问题:
整合(Aggregation)——即分组计算统计量(如求均值、求每组元素个数)
变换(Transformation)——即分组对每个单元的数据进行操作(如元素标准化)
过滤(Filtration)——即按照某些规则筛选出一些组(如选出组内某一指标小于50的组)
综合问题——即前面提及的三种问题的混合
二、groupby函数
1. groupby分组函数的基本内容
单/多列分组
经过groupby后会生成一个groupby对象,该对象本身不会返回任何东西,只有当相应的方法被调用才会起作用。
grouped_single = df.groupby('School')
print(grouped_single)
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f10981146d0>
print(grouped_single.get_group('S_1').head())
打印了School为S_1的
School Class Gender Address Height Weight Math Physics
ID
1101 S_1 C_1 M street_1 173 63 34.0 A+
1102 S_1 C_1 F street_2 192 73 32.5 B+
1103 S_1 C_1 M street_2 186 82 87.2 B+
1104 S_1 C_1 F street_2 167 81 80.4 B-
1105 S_1 C_1 F street_4 159 64 84.8 B+
grouped_mul = df.groupby(['School','Class'])
grouped_mul.get_group(('S_2','C_4'))
根据多列分组
School Class Gender Address Height Weight Math Physics
ID
2401 S_2 C_4 F street_2 192 62 45.3 A
2402 S_2 C_4 M street_7 166 82 48.7 B
2403 S_2 C_4 F street_6 158 60 59.7 B+
2404 S_2 C_4 F street_2 160 84 67.7 B
2405 S_2 C_4 F street_6 193 54 47.6 B
组容量与组数
print('组容量与组数')
print(grouped_single.size())
print(grouped_mul.size())
print(grouped_single.ngroups)
print(grouped_mul.ngroups)
组容量与组数
School
S_1 15
S_2 20
dtype: int64
School Class
S_1 C_1 5
C_2 5
C_3 5
S_2 C_1 5
C_2 5
C_3 5
C_4 5
dtype: int64
2
7
组的遍历
for name,group in grouped_single:
print(name)
print(group)
S_1
School Class Gender Address Height Weight Math Physics
ID
1101 S_1 C_1 M street_1 173 63 34.0 A+
1102 S_1 C_1 F street_2 192 73 32.5 B+
1103 S_1 C_1 M street_2 186 82 87.2 B+
1104 S_1 C_1 F street_2 167 81 80.4 B-
1105 S_1 C_1 F street_4 159 64 84.8 B+
1201 S_1 C_2 M street_5 188 68 97.0 A-
1202 S_1 C_2 F street_4 176 94 63.5 B-
1203 S_1 C_2 M street_6 160 53 58.8 A+
1204 S_1 C_2 F street_5 162 63 33.8 B
1205 S_1 C_2 F street_6 167 63 68.4 B-
1301 S_1 C_3 M street_4 161 68 31.5 B+
1302 S_1 C_3 F street_1 175 57 87.7 A-
1303 S_1 C_3 M street_7 188 82 49.7 B
1304 S_1 C_3 M street_2 195 70 85.2 A
1305 S_1 C_3 F street_5 187 69 61.7 B-
S_2
School Class Gender Address Height Weight Math Physics
ID
2101 S_2 C_1 M street_7 174 84 83.3 C
2102 S_2 C_1 F street_6 161 61 50.6 B+
2103 S_2 C_1 M street_4 157 61 52.5 B-
2104 S_2 C_1 F street_5 159 97 72.2 B+
2105 S_2 C_1 M street_4 170 81 34.2 A
2201 S_2 C_2 M street_5 193 100 39.1 B
2202 S_2 C_2 F street_7 194 77 68.5 B+
2203 S_2 C_2 M street_4 155 91 73.8 A+
2204 S_2 C_2 M street_1 175 74 47.2 B-
2205 S_2 C_2 F street_7 183 76 85.4 B
2301 S_2 C_3 F street_4 157 78 72.3 B+
2302 S_2 C_3 M street_5 171 88 32.7 A
2303 S_2 C_3 F street_7 190 99 65.9 C
2304 S_2 C_3 F street_6 164 81 95.5 A-
2305 S_2 C_3 M street_4 187 73 48.9 B
2401 S_2 C_4 F street_2 192 62 45.3 A
2402 S_2 C_4 M street_7 166 82 48.7 B
2403 S_2 C_4 F street_6 158 60 59.7 B+
2404 S_2 C_4 F street_2 160 84 67.7 B
2405 S_2 C_4 F street_6 193 54 47.6 B
level参数(用于多级索引)和axis参数
参数level,指明聚合的层级
print(df.set_index(['Gender','School']).groupby(level=1,axis=0).get_group('S_1').head()
level就是school,也可以直接用’school’——df.set_index(['Gender','School']).groupby(level='School',axis=0).get_group('S_1').head())
Class Address Height Weight Math Physics
Gender School
M S_1 C_1 street_1 173 63 34.0 A+
F S_1 C_1 street_2 192 73 32.5 B+
M S_1 C_1 street_2 186 82 87.2 B+
F S_1 C_1 street_2 167 81 80.4 B-
S_1 C_1 street_4 159 64 84.8 B+
2.groupby对象的特点
print([attr for attr in dir(grouped_single) if not attr.startswith('_')])
[‘Address’, ‘Class’, ‘Gender’, ‘Height’, ‘Math’, ‘Physics’, ‘School’, ‘Weight’, ‘agg’, ‘aggregate’, ‘all’, ‘any’, ‘apply’, ‘backfill’, ‘bfill’, ‘boxplot’, ‘corr’, ‘corrwith’, ‘count’, ‘cov’, ‘cumcount’, ‘cummax’, ‘cummin’, ‘cumprod’, ‘cumsum’, ‘describe’, ‘diff’, ‘dtypes’, ‘expanding’, ‘ffill’, ‘fillna’, ‘filter’, ‘first’, ‘get_group’, ‘groups’, ‘head’, ‘hist’, ‘idxmax’, ‘idxmin’, ‘indices’, ‘last’, ‘mad’, ‘max’, ‘mean’, ‘median’, ‘min’, ‘ndim’, ‘ngroup’, ‘ngroups’, ‘nth’, ‘nunique’, ‘ohlc’, ‘pad’, ‘pct_change’, ‘pipe’, ‘plot’, ‘prod’, ‘quantile’, ‘rank’, ‘resample’, ‘rolling’, ‘sem’, ‘shift’, ‘size’, ‘skew’, ‘std’, ‘sum’, ‘tail’, ‘take’, ‘transform’, ‘tshift’, ‘var’]
groupby对象可以使用相当多的函数,灵活程度很高
分组对象的head和first
grouped_single.head(2)
对分组对象使用head函数,返回的是每个组的前几行,而不是数据集前几行。
first显示的是以分组为索引的每组的第一个分组信息。grouped_single.first()
分组依据
对于groupby函数而言,分组的依据是非常自由的,只要是与数据框长度相同的列表即可,同时支持函数型分组。
df.groupby(np.random.choice(['a','b','c'],df.shape[0])).get_group('a').head()
#相当于将np.random.choice(['a','b','c'],df.shape[0])当做新的一列进行分组
从原理上说,我们可以看到利用函数时,传入的对象就是索引,因此根据这一特性可以做一些复杂的操作。比如根据奇偶行分组:
df.groupby(lambda x:'奇数行' if not df.index.get_loc(x)%2==1 else '偶数行').groups
{'偶数行': Int64Index([1102, 1104, 1201, 1203, 1205, 1302, 1304, 2101, 2103, 2105, 2202,
2204, 2301, 2303, 2305, 2402, 2404],
dtype='int64', name='ID'),
'奇数行': Int64Index([1101, 1103, 1105, 1202, 1204, 1301, 1303, 1305, 2102, 2104, 2201,
2203, 2205, 2302, 2304, 2401, 2403, 2405],
dtype='int64', name='ID')}
m.groups() 返回所有括号匹配的字符,以tuple格式。
m.groups() == (m.group(0), m.group(1), …)
如果是多层索引,那么lambda表达式中的输入就是元组,下面实现的功能为查看两所学校中男女生分别均分是否及格。注意:此处只是演示groupby的用法,实际操作不会这样写。
math_score = df.set_index(['Gender','School'])['Math'].sort_index()
grouped_score = df.set_index(['Gender','School']).sort_index().\
groupby(lambda x:(x,'均分及格' if math_score[x].mean()>=60 else '均分不及格'))
for name,_ in grouped_score: