第1章 入门知识
- 简述:用于操作行列数据,方便地实现各种形式的数据分析;
- Pandas最初主要应用于金融数据分析工作,其为时间序列分析提供了很好的支持;
- Pandas的名称来自于面板数据
(panel data)
和Python数据分析(data analysis)
; -
panel data
是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型(新版本已停用); - 适用的数据类型
- 具有异构类型列的表格数据,如SQL表格或Excel数据;
- 有序和无序(不一定是固定频率)时间序列数据;
- 具有行列标签的任意矩阵数据(均匀类型或不同类型);
- 任何其他形式的观测/统计数据集。
第2章 数据结构
- 作为一个python库,python中的数据类型在pandas中依然适用
- 核心数据结构
-
Series
:一维、带有索引、同类型元素的数组,与Numpy
中的一维array类似; -
DateFrame
:二维、带有索引、大小可变、可以不同类型元素的表格数据,可以看作是Series的容器,即一个DateFrame
可以包含若干个Series
。
第3章 创建对象
-
Series
:标量值列表,默认索引为整数;pd.Series([1, 3, 5, np.nan, 6, 8]) 0 1.0 1 3.0 2 5.0 3 NaN 4 6.0 5 8.0 dtype: float64
-
Dataframe
:带有日期时间的索引、Numpy数组;dates = pd.date_range('2018-07-10', periods=6) dates -- > DatetimeIndex(['2018-07-10', '2018-07-11', '2018-07-12', '2018-07-13','2018-07-14', '2018-07-15'], dtype='datetime64[ns]', freq='D') df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD')) print(df) A B C D 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 2018-07-14 -0.438337 0.270277 -1.208112 1.982913 2018-07-15 0.863050 0.442406 0.871964 1.107883
-
Dataframe
:可以转换为类似Series系列的dict对象;df2 = pd.DataFrame({ 'A':1., 'B':pd.Timestamp('20180710'), 'C':pd.Series(1, index=list(range(4)), dtype='float32'), 'D':np.array([2]*4, dtype='int32'), 'E':np.array([1, 2, 3, 4], dtype='int64'), 'F':pd.Categorical(['test', 'learn', 'test', 'learn']), 'G':'xz' }) print(df2) A B C D E F G 0 1.0 2018-07-10 1.0 2 1 test xz 1 1.0 2018-07-10 1.0 2 2 learn xz 2 1.0 2018-07-10 1.0 2 3 test xz 3 1.0 2018-07-10 1.0 2 4 learn xz
- DataFrame的不同列,具有不同的
dtypes
。print(df2.dtypes) A float64 B datetime64[ns] C float32 D int32 E int64 F category G object dtype: object
第4章 查看数据
-
head(x)
查看顶行数据、tail(x)
查看底行数据,x
表示查看的行数,默认为5;df2.head(2) #查看顶部2行数据 A B C D E F G 0 1 2018-07-10 1 2 1 test xz 1 1 2018-07-10 1 2 2 learn xz df2.tail(3) # 查看底部3行数据 A B C D E F G 1 1 2018-07-10 1 2 2 learn xz 2 1 2018-07-10 1 2 3 test xz 3 1 2018-07-10 1 2 4 learn xz
- 查看索引、列名称、基础Numpy数据;
df2.index -- > Int64Index([0, 1, 2, 3], dtype='int64') df2.columns -- > Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object') df2.values array([[1.0, Timestamp('2018-07-10 00:00:00'), 1.0, 2, 1, 'test', 'xz'], [1.0, Timestamp('2018-07-10 00:00:00'), 1.0, 2, 2, 'learn', 'xz'], [1.0, Timestamp('2018-07-10 00:00:00'), 1.0, 2, 3, 'test', 'xz'], [1.0, Timestamp('2018-07-10 00:00:00'), 1.0, 2, 4, 'learn', 'xz']], dtype=object)
- 描述性统计;
df.describe() A B C D count 6.000000 6.000000 6.000000 6.000000 mean -0.203846 -0.520712 0.252811 0.056574 std 1.824972 0.629551 1.047736 0.535639 min -2.441260 -1.616401 -0.849088 -0.795480 25% -1.805976 -0.669989 -0.564042 -0.165330 50% 0.214104 -0.472665 0.257587 0.142493 75% 1.160094 -0.065817 0.595098 0.291087 max 1.793887 0.103427 1.981094 0.777256
- 转置数据
df2.T 0 1 2 3 A 1 1 1 1 B 2018-07-10 00:00:00 2018-07-10 00:00:00 2018-07-10 00:00:00 2018-07-10 00:00:00 C 1 1 1 1 D 2 2 2 2 E 1 2 3 4 F test learn test learn G xz xz xz xz
第5章 选取数据
- 获取一列,即Series
df.A # 等同于 df['A'] 2018-07-10 -0.177312 2018-07-11 -2.441260 2018-07-12 -2.348864 2018-07-13 0.605520 2018-07-14 1.344952 2018-07-15 1.793887 Freq: D, Name: A, dtype: float64
- 行切片:索引或值
df[:3] # 索引切片 A B C D 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 df['2018-07-11':'2018-07-14'] # 值切片 A B C D 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 2018-07-14 -0.438337 0.270277 -1.208112 1.982913
- 函数:
loc[]、iloc[]
-
loc[]
:根据行或列的索引值,获取数据,含下限
,可仅取行或列; -
iloc[]
:根据行或列的索引位置,获取数据,不含下限
,可仅取行或列; - 仅取一行
df.loc['2018-07-11'] 等同于 df.iloc[1] A -1.508561 B -0.173393 C 0.815395 D -1.242897 Name: 2018-07-11 00:00:00, dtype: float64
- 仅取一列
df.loc[:,'C'] 等同于 df.iloc[:,2] 2018-07-10 0.809279 2018-07-11 0.815395 2018-07-12 -0.915480 2018-07-13 -1.636825 2018-07-14 -1.208112 2018-07-15 0.871964 Freq: D, Name: C, dtype: float64
- 行列连续截取
df.loc['2018-07-12':'2018-07-14',['B', 'C', 'D']] 等同于 df.iloc[2:5, 1:4] B C D 2018-07-12 -0.462607 -0.915480 2.595037 2018-07-13 -0.216765 -1.636825 -0.671588 2018-07-14 0.270277 -1.208112 1.982913 说明:loc[]在选取行索引值时,可以类似切片的形式,但是在选取列索引时,只能一个一个列举,不能像类似切片的形式用冒号连接取连续的中间值。
- 行列不连续截取
df.iloc[[0,5],[0,3]] # iloc[]行列均可以不连续截取数据 A D 2018-07-10 -0.710755 -0.718210 2018-07-15 0.863050 1.107883 df.loc['2017-07-10':'2018-07-15', ['A', 'D']] # loc[]行索引 不 可以不连续截取 A D 2018-07-10 -0.710755 -0.718210 2018-07-11 -1.508561 -1.242897 2018-07-12 -2.157823 2.595037 2018-07-13 0.826433 -0.671588 2018-07-14 -0.438337 1.982913 2018-07-15 0.863050 1.107883
- 获取单个值
df.loc['2018-07-14', 'C'] 等同于 df.iloc[4,2] -1.2081117496772031
- 补充:
loc[]、iloc[]
方法也可以对DataFrame进行赋值等操作。
- 布尔判断:多列值判断时,
&
表示and的关系,|
表示or的关系df[df.C < 0.5] #单个列值判断 A B C D 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 2018-07-14 -0.438337 0.270277 -1.208112 1.982913 df[(df.A < 0) & (df.D > 0)] A B C D 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 2018-07-14 -0.438337 0.270277 -1.208112 1.982913 df[df > 0] #DataFrame值判断 A B C D 2018-07-10 NaN NaN 0.809279 NaN 2018-07-11 NaN NaN 0.815395 NaN 2018-07-12 NaN NaN NaN 2.595037 2018-07-13 0.826433 NaN NaN NaN 2018-07-14 NaN 0.270277 NaN 1.982913 2018-07-15 0.863050 0.442406 0.871964 1.107883
- 过滤函数:
isin()
df2 = df.copy() df2['E'] = ['one', 'two', 'three', 'four', 'five', 'six'] print(df2) A B C D E 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 one 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 two 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 three 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 four 2018-07-14 -0.438337 0.270277 -1.208112 1.982913 five 2018-07-15 0.863050 0.442406 0.871964 1.107883 six df2[df2.E.isin(['two', 'five'])] A B C D E 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 two 2018-07-14 -0.438337 0.270277 -1.208112 1.982913 five
- 模糊匹配:
contains()
df2[df2.E.str.contains('o')] # 选取E列中含有关键字“o”的数据 A B C D E 2018-07-10 -1.738617 -1.013051 -1.938631 -1.049786 one 2018-07-11 -0.719089 -1.042707 -0.616299 0.460417 two 2018-07-13 -0.446243 -2.036736 1.469567 0.256282 four
- 获取数据的方法,同样可以对DataFrame进行重新赋值。
第6章 缺失值
- Pandas使用
np.nan
来表示缺失的数据,默认不包含在计算中; - 准备数据
df3 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E']) # 增加索引,默认数据均为空 df3.iloc[0:2, 4] = 1 # 赋值 print(df3) A B C D E 2018-07-10 -0.177312 -0.456757 -0.849088 0.107067 1 2018-07-11 -2.441260 -0.730461 1.981094 0.177919 1 2018-07-12 -2.348864 0.103427 0.607445 -0.795480 NaN 2018-07-13 0.605520 -0.488574 0.558058 0.328810 NaN
- 删除任何缺少数据的行
df3.dropna(how='any') # axis=1时删除列数据、how=all时所有值均为空时才删除 A B C D E 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 1.0 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 1.0
- 替换缺失值
df3.fillna(1000) #将空值替换为1000 A B C D E 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 1.0 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 1.0 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 1000.0 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 1000.0
- 判断缺失值
pd.isna(df3) # 不同的pandas版本,可以用isnull() A B C D E 2018-07-10 False False False False False 2018-07-11 False False False False False 2018-07-12 False False False False True 2018-07-13 False False False False True
第7章 排序
- 按索引排序
- 语法:
sort_index(axis=0/1, ascengding=True/False)
- axis缺失或为0时,按行索引排序,为1时按列索引(columns)排序;
- ascengding缺失或为True时,表示升序,为False时表示降序;
- 示例
df3.sort_index(axis=1, ascending=False) #列排序,降序 E D C B A 2018-07-10 1.0 -0.718210 0.809279 -0.757183 -0.710755 2018-07-11 1.0 -1.242897 0.815395 -0.173393 -1.508561 2018-07-12 NaN 2.595037 -0.915480 -0.462607 -2.157823 2018-07-13 NaN -0.671588 -1.636825 -0.216765 0.826433
- 按值排序
- 语法:
sort_values(by='colums_name', ascengding=True/False)
- 示例
df3.sort_values(by=['D', 'C'], ascending=False) A B C D E 2018-07-12 -2.157823 -0.462607 -0.915480 2.595037 NaN 2018-07-13 0.826433 -0.216765 -1.636825 -0.671588 NaN 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 1.0 2018-07-11 -1.508561 -0.173393 0.815395 -1.242897 1.0
- 自定义排序
- 步骤
- 第一步:将需要自定义排序的字段,设置为“category”数据类型
- 第二步:对字段进行自定义排序
- 第三步:对DataFrame进行排序
- 准备数据
df_sort = pd.DataFrame({ "word":['a', 'b', 'c'], "number":[1, 2, 3]}) print(df_sort) word number 0 a 1 1 b 2 2 c 3 # 需要排列的顺序 sort_column = ['c', 'b', 'a']
- 示例
df_sort.word = df.word.astype('category') #把排序字段设置为"category"类型 df_sort.word.cat.reorder_categories(sort_column, inplace=True) # 字段按自定义排序 df_sort.sort_values('word',inplace=True) # DataFrame按自定义排序 print(df_sort) word number 2 c 3 1 b 2 0 a 1
第8章 常用操作
- 统计:
mean(x)
、count(x)
、min(x)
、max(x)
、std(x)
等,x
为0时是行操作、x
为1时是列操作。统计时上述函数会忽略缺失值。df3.mean() #统计每列的均值 A -0.887676 B -0.402487 C -0.231908 D -0.009415 E 1.000000 dtype: float64 df3.max(1) #统计每行的最大值 2018-07-10 1.000000 2018-07-11 1.000000 2018-07-12 2.595037 2018-07-13 0.826433 Freq: D, dtype: float64
- 函数:
apply()
df3.apply(np.cumsum) #统计每列的累加和 A B C D E 2018-07-10 -0.710755 -0.757183 0.809279 -0.718210 1.0 2018-07-11 -2.219316 -0.930576 1.624674 -1.961108 2.0 2018-07-12 -4.377138 -1.393183 0.709194 0.633930 NaN 2018-07-13 -3.550705 -1.609948 -0.927632 -0.037658 NaN df3.apply(lambda x: x.max() - x.min(), axis=1) #统计每行最大值与最小值之差 2018-07-10 1.757183 2018-07-11 2.508561 2018-07-12 4.752860 2018-07-13 2.463258 Freq: D, dtype: float64
- 求和、不同值计数
np.sum(df3.C) # 对C列求和 -0.927631569447292 df3.E.value_counts() # 对E列不同值计数,自动忽略空值 1.0 2 Name: E, dtype: int64
- 字符串方法
str
df4 = pd.DataFrame({"A":['foo', 'bar', 'bar', 'xz'], "B":['one', 'two', 'one', 'two'], "C":['Small', 'Small', 'Large', 'Large'], "D":[1, 2, 3, 4]}) print(df4) A B C D 0 foo one Small 1 1 bar two Small 2 2 bar one Large 3 3 xz two Large 4 df4.C.str.lower() # 字符串转换为 小写 0 small 1 small 2 large 3 large Name: C, dtype: object df4[df4.A.str.endswith('r')] #字符串结尾字符筛选 A B C D 1 bar two Small 2 2 bar one Large 3
第9章 合并
- 关联
merge()
- 用法:通过
键
横向拼接列
,类似sql中的join,通过一个或多个
键将不同的DataFrame关联 - 参数说明
-
how : inner、outer、left、right
关联方式 -
on : [key1, key2......]
同字段名关联 -
left_on / right_on 、 left_key / right_key、left_index / right_index
不同字段名关联 - left_index / right_index = True时,表示按索引进行匹配
-
- 多对多关联
left = pd.DataFrame({'key':['xz', 'xz'], 'value':[1, 2]}) print(left) key value 0 xz 1 1 xz 2 right = pd.DataFrame({'key':['xz', 'xz'], 'value':[5, 6]}) print(right) key value 0 xz 5 1 xz 6 join = pd.merge(left, right, on='key') #多对多关联 print(join) key value_x value_y 0 xz 1 5 1 xz 1 6 2 xz 2 5 3 xz 2 6
- 一对一关联
left = pd.DataFrame({'key':['xz', 'ab'], 'value':[1, 2]}) print(left) key value 0 xz 1 1 ab 2 right = pd.DataFrame({'key':['xz', 'ab'], 'value':[5, 6]}) print(right) key value 0 xz 5 1 ab 6 join = pd.merge(left, right, on='key') # 一对一关联 print(join) key value_x value_y 0 xz 1 5 1 ab 2 6
- 追加
append()
- 用法:
纵向
追加数据,横向同时扩充,不考虑columns和index,数据列不一样时,设置ignore_index = True
; - 示例
df5 = pd.DataFrame(np.random.randint(10, 20, [2,4]),columns=list('ABCD')) print(df5) A B C D 0 19 16 15 15 1 16 15 16 10 s = df5[1:] print(s) A B C D 1 16 15 16 10 df5.append(s, ignore_index=True) # ignore_index:默认为False, 若为True,表示不要使用索引标签 A B C D 0 19 16 15 15 1 16 15 16 10 2 16 15 16 10
- 拼接
concat()
- 用法:单纯的表拼接,可以
横向
或纵向
,可以一次性拼接多个表,结果不去重复,需要指定轴进行连接,drop_duplicates()可以去重复。 - 参数说明
-
objs
:连接对象,如:Series、DataFrame、list -
axis
= 0 时,与append()
方法相同;axis
= 1时,与merge()
方法相同 -
join
:inner、outer(默认) -
join_axes
:设置需要保留的表索引 -
ignore_index
:是否忽略原索引 -
keys
:为原连接对象添加一个键,便于后期分组统计
-
- 示例
df6 = pd.DataFrame(np.random.randn(8, 4)) print(df6) 0 1 2 3 0 1.259128 1.352209 0.934947 0.734223 1 -0.567591 -1.114880 -1.540007 0.192176 2 1.007433 0.774980 1.229243 1.413190 3 1.029385 0.316052 0.363644 1.310764 4 -0.414858 2.030369 1.910180 -0.785533 5 0.684923 -0.064547 -1.475371 -0.842338 6 -0.289478 2.119747 0.519206 -2.564895 7 0.958962 -1.278468 0.099762 0.226029 pd.concat([df6[:2], df6[3:5], df6[7:]], keys=['x', 'y', 'z']) 0 1 2 3 x 0 1.259128 1.352209 0.934947 0.734223 1 -0.567591 -1.114880 -1.540007 0.192176 y 3 1.029385 0.316052 0.363644 1.310764 4 -0.414858 2.030369 1.910180 -0.785533 z 7 0.958962 -1.278468 0.099762 0.226029
- 合并
join()
- 用法:默认以
index
为拼接列,其参数与merge方法基本一致,默认 how = left ,可以合并相同或相似的索引,目前已较少使用。
第10章 分组
-
单列分组--单列运算
df7 = pd.DataFrame({'A': list('XYZXYZXYZX'), 'B': [1, 2, 1, 3, 1, 2, 3, 3, 1, 2], 'C': [12, 14, 11, 12, 13, 14, 16, 12, 10, 19]}) print(df7) A B C 0 X 1 12 1 Y 2 14 2 Z 1 11 3 X 3 12 4 Y 1 13 5 Z 2 14 6 X 3 16 7 Y 3 12 8 Z 1 10 9 X 2 19 df7.groupby('A').C.mean() # 按A列分组,统计C列的均值 A X 14.750000 Y 13.000000 Z 11.666667 Name: C, dtype: float64
-
单列分组--单列多种运算
df7.groupby('A').B.agg([np.mean,np.std]) mean std A X 2.250000 0.957427 Y 2.000000 1.000000 Z 1.333333 0.577350
-
单列分组--多列相同运算
df7.groupby('A')['B', 'C'].mean() B C A X 2.250000 14.750000 Y 2.000000 13.000000 Z 1.333333 11.666667
-
单列分组--多列不同运算
df7.groupby('A')['B', 'C'].agg({'B': 'count', 'C': 'sum'}) B C A X 4 59 Y 3 39 Z 3 35 说明:在分组统计时,一般的统计函数会自动忽略空值,计数时使用`size()`函数,会包含空值。
-
单列分组--多列多个不同运算
df7.groupby('A').agg({'B':[np.mean, 'sum'], 'C':['count', np.std]}) B C mean sum count std A X 2.250000 9 4 3.403430 Y 2.000000 6 3 1.000000 Z 1.333333 4 3 2.081666
-
多列分组--单列运算
df7.groupby(['A', 'B']).C.sum() A B X 1 12 2 19 3 28 Y 1 13 2 14 3 12 Z 1 21 2 14 说明:多列分组后的各种运算,和单列分组后一样,不再举例。
-
函数
apply()+lambda()
df7.groupby('A').apply(lambda x: (x['C'] - x['B']).mean()) # B列与C列之差的均值 A X 12.500000 Y 11.000000 Z 10.333333
函数
transform()
- 聚合运算时,通常输出的结果是一个以分组名为 index 的结果对象,若需要使用原数组的 index ,即把聚合结果关联到原数组对象时,使用该函数。
- 示例
# 普通的分组 df7.groupby(['A', 'B']).C.count() A B X 1 1 2 1 3 2 Y 1 1 2 1 3 1 Z 1 2 2 1 df7['count'] = df7.groupby(['A', 'B']).C.transform('count') print(df7) A B C count 0 X 1 12 1 1 Y 2 14 1 2 Z 1 11 2 3 X 3 12 2 4 Y 1 13 1 5 Z 2 14 1 6 X 3 16 2 7 Y 3 12 1 8 Z 1 10 2 9 X 2 19 1
- 分段分组
- 分段函数
cut()
:将数据值分段,主要用于将连续变量转换为分类变量 - 等距离分段:数据中的最小值和最大值,左右侧各扩展0.1%,做为分段边界;
df8 = pd.DataFrame({'Age': np.random.randint(20, 70, 15), 'Sex': np.random.choice(['Male', 'Female'], 15), 'num': np.random.randint(1, 20, 15)}) print(df8) Age Sex num 0 22 Male 6 1 49 Male 12 2 52 Female 13 3 29 Female 1 4 46 Male 18 5 64 Female 2 6 42 Male 9 7 33 Male 15 8 25 Male 16 9 38 Male 4 10 32 Male 8 11 28 Male 8 12 31 Male 8 13 62 Male 6 14 40 Male 13 pd.cut(df8['Age'], bins=3) #等距离分割 0 (21.958, 36.0] 1 (36.0, 50.0] 2 (50.0, 64.0] 3 (21.958, 36.0] 4 (36.0, 50.0] 5 (50.0, 64.0] 6 (36.0, 50.0] 7 (21.958, 36.0] 8 (21.958, 36.0] 9 (36.0, 50.0] 10 (21.958, 36.0] 11 (21.958, 36.0] 12 (21.958, 36.0] 13 (50.0, 64.0] 14 (36.0, 50.0] Name: Age, dtype: category Categories (3, interval[float64]): [(21.958, 36.0] < (36.0, 50.0] < (50.0, 64.0]] df8.groupby(pd.cut(df8['Age'], bins=3)).mean() # 等距分组 Age num Age (21.958, 36.0] 28.571429 8.857143 (36.0, 50.0] 43.000000 11.200000 (50.0, 64.0] 59.333333 7.000000
- 自定义范围分段:范围段可以不均匀
pd.cut(df8['Age'], bins=[0,30,50,np.inf]) #自定义范围进行分割,可以不均匀 0 (50.0, inf] 1 (0.0, 30.0] 2 (50.0, inf] 3 (0.0, 30.0] 4 (30.0, 50.0] 5 (50.0, inf] 6 (50.0, inf] 7 (30.0, 50.0] 8 (0.0, 30.0] 9 (30.0, 50.0] 10 (50.0, inf] 11 (0.0, 30.0] 12 (50.0, inf] 13 (30.0, 50.0] 14 (50.0, inf] Name: Age, dtype: category Categories (3, interval[float64]): [(0.0, 30.0] < (30.0, 50.0] < (50.0, inf]] # 自定义分段进行分组统计 df8.groupby(pd.cut(df8['Age'], bins=[0, 30, 50, np.inf])).mean() Age num Age (0.0, 30.0] 23.250000 8.250000 (30.0, 50.0] 37.000000 9.250000 (50.0, inf] 59.428571 10.428571
- 统计频率
- 交叉表
crosstab()
:一种特殊的pivot_table(),主要于计算分段分组频率; - 对指定列分段后,再进行分组,经常需要计算分组频率;
- 对字段
Age
分段后,计算Sex
的分组频率,即按 Age 的分组范围和性别 Sex 进行制作交叉表。pd.crosstab(pd.cut(df8.Age, bins=[0, 30, 50, np.inf]), df8.Sex) Sex Female Male Age (0.0, 30.0] 1 3 (30.0, 50.0] 0 8 (50.0, inf] 2 1
第11章 透视表
pivot_table()
- 参数说明
param | instroduction |
---|---|
data | DataFrame |
value | 待聚合的列名称,默认聚合所有数据列 |
index | 用于分组的列名或其他分组键,出现在结果透视表的行 |
columns | 用于分组的列名或其他分组键,出现在结果透视表的列 |
aggfunc | 聚合函数或函数列表,默认为mean 。可以使任何对groupby有效的函数 |
fill_value | 用于替换结果表中的缺失值 |
dropna | boolean,默认为True |
margins | 是否添加汇总的行列 |
margins_name | 默认为all ,margins=True时设置汇总行列的名称 |
- 准备数据
df9 = pd.DataFrame({ "A": ["foo", "foo", "foo", "foo", "foo","bar", "bar", "bar", "bar"], "B": ["one", "one", "one", "two", "two","one", "one", "two", "two"], "C": ["small", "large", "large", "small","small", "large", "small", "small","large"], "D": [1, 2, 3, 4, 3, 4, 5, 6, 7]}) print(df9) A B C D 0 foo one small 1 1 foo one large 2 2 foo one large 3 3 foo two small 4 4 foo two small 3 5 bar one large 4 6 bar one small 5 7 bar two small 6 8 bar two large 7
- 默认聚合方法
pd.pivot_table(df9, index=['A', 'B'], columns='C', values='D') #默认聚合函数为均值 C large small A B bar one 4.0 5.0 two 7.0 6.0 foo one 2.5 1.0 two NaN 3.5
- 设置聚合方法
# 设置单个聚合方法 pd.pivot_table(df9, index=['A', 'B'], columns='C', values='D', aggfunc=np.sum, fill_value=0) #求和、空值设置为0 C large small A B bar one 4 5 two 7 6 foo one 5 1 two 0 7 # 设置多个聚合方法 df9['E'] = [8, 9, 10, 11, 12, 13, 14, 15, 16] pd.pivot_table(df13, values=['D', 'E'], index=['A', 'C'], aggfunc={'D': np.mean, 'E': [min, max, np.median]}) D E mean max median min A C bar large 5.500000 16 14.5 13 small 5.500000 15 14.5 14 foo large 2.500000 10 9.5 9 small 2.666667 12 11.0 8
pivot()
- 透视后,不进行统计处理,主要用来处理非数字数据,进行行列转换;
- 其
index
只能是一个指定的列,index
和columns
对应的数据元组,不能有重复,否则会报错。 - 准备数据
df10 = pd.DataFrame({ "A": ["foo", "bar", "bar", "xz"], "B": ["one", "two", "one", "two"], "C": ["small", "large", "large", "small"], "D": [1, 2, 3, 4]}) print(df10) A B C D 0 foo one small 1 1 bar two large 2 2 bar one large 3 3 xz two small 4
- 示例
df10.pivot(index='A', columns='B', values='D') B one two A bar 3.0 2.0 foo 1.0 NaN xz NaN 4.0
第12章 其它
- 操作文件
- 以csv格式文件为例,读取
read_csv()
、写入to_csv()
- 常见格式:excel、txt、sql、html、json等
- 常用操作
- 查看列的数据类型:
df.dtypes
- 查看数据详情:
df.info()
- 删除A列 :
df.drop(A, axis = 1)
- 更改列名 :
df = df.rename(columns = {'old_name': 'new_name'})
- 替换值 :
df.replace(to_replace, values)
- 设置列数据类型:
df.A = df.A.values.astype(‘float64’)
- 日期字符串转date:
pd.to_datetime(df.date).dt.date
- 日期字符串转时间戳:
pd.to_datetime(df.date).dt.to_pydatetime()
- 时间处理:
dt
- 用途:作用于
datetime64[ns]
/timedelta64[ns]
等日期型数据,获取datetimelike
属性的Accessor
对象 - 设置日期格式 :
dt.strftime()
- 获取日期中的信息:
dt.date
/dt.year
/dt.month
/dt.time
/dt.weekday
/dt.dayofyear
/dt.weekofyear
- 设置日期运算单位 :
[datetime1 - datetime2].dt.days
- 合并列:
cat
- 语法:
df['A'].str.cat([df['B'], df['C']], sep='-')
- 合并的2列的内容必须是字符串,如果是数值型则会报错,需要先转换类型;
- 当需要将某列的内容都加上一个指定字符时,可以先创建一个由该字符组成的临时列,再合并。
-
DataFrame
四则运算
-
add
: 加法运算,举例:DataFrame1
.add(DataFrame2
, fill_value=0) -
sub
: 减法运算,举例:DataFrame1
.sub(DataFrame2
, fill_value=0) -
mul
: 乘法运算,举例:DataFrame1
.mul(DataFrame2
) -
div
: 除法运算,举例:DataFrame1
.div(DataFrame2
) -
说明
: 上述参数DataFrame2
可以是:Series、DataFrame、constant
,Series类型的数据,也有类似如上的四则运算。
- 设置显示选项 :
pandas.set_option(pat, value)
- 保留小数点后的n位数:
("precision", n)
- 展示n列:
("max_columns", n)
- 展示n行:
("max_rows", n)
- 绝对值小于n的显示为0:
("chop_threshold", n)
- pd.options.mode.chained_assignment = None :关闭掉copywarning
- pd.options.display.max_columns = 999 :设置显示的列数
- 常见的小坑
- 空
DataFrame
合并一个Series
时,会重新排列生成的列顺序,默认按字母顺序。特别是,使用loc[]
或iloc[]
选取的Series
,建议,先to_frame().T
转成DataFrame
后再合并 - 列中类似:date、datetime、time型的字符串数据,需要转为
datetime64[ns]
日期数据,如df.date = pd.to_datetime(df.date)
,才能进行选取:df[df.date == '2018-11-11']
- 列中
datetime64[ns]
日期数据,进行大小判断选取数据时,与空值比较,结果为空; - 数据列中存在空数据
NaN
,使用astype()
对其数据类型进行转化时,需要先将空数据NaN
排除掉,否则函数不起作用。其参数errors
只是对无法进行转换类型的数据(非空)进行处理; - 对
df[df.condition] = value
,即重新赋值时,会报警,解决办法:需要重新copy()一份,即df[df.condition].copy()后,再赋值。
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
- groupby分组后,需要统计的字段较多且有条件判断时,使用apply() + lambda + pd.Series()来快速实现;
- 在pandas中,没有isnotin函数,可以通过取反的方式实现,取反的方法就是在函数前面加个
~
。例如:~(df.A == 4) ,等效于 df.A != 4。