1. 统计
1.1 groupby()函数
使用映射器或一系列列对 DataFrame 进行分组。
groupby操作涉及分割对象、应用函数以及组合结果的某种组合。这可用于对大量数据进行分组并在这些组上进行计算操作。
DataFrame.groupby(by=None,
axis=_NoDefault.no_default,
level=None,
as_index=True,
sort=True,
group_keys=True,
observed=_NoDefault.no_default,
dropna=True)
参数说明:
参数名 | 说明 |
by | mapping, function, label, pd.Grouper 或者 list of such。用于确定groupby的组 label示例:df.groupby('category') list示例:df.groupby(['category']) mapping:需要按DataFrame的index进行映射,用于对category添加汇总分类。 这里把水果和蔬菜划分到大组蔬菜水果,米面和粮油划分到大组米面粮油 示例:df.groupby({0:"水果蔬菜",1:"水果蔬菜",2:"米面粮油",...}) function:自定义函数的入参也是DataFrame的index,输出结果与mapping的例子相同 |
axis | {0 或 'index', 1 或 'columns'}, 默认 0 |
level | 当axis是MultiIndex(层级结构)时,按特定的level进行分组,注意这里的level是int类型,从0开始,0表示第1层,以此类推。不要同时指定by和level。 |
as_index | bool, 默认 True 返回以组标签作为索引的对象。仅与 DataFrame 输入相关。 as_index=False 实际上是“SQL 风格”的分组输出。此参数对过滤(请参阅用户指南中的过滤)没有影响,例如head()\、tail()和nth()转换。 |
sort | bool,默认 True 对组键进行排序。关闭此功能可获得更好的性能。请注意,这不会影响每组内的观察顺序。Groupby保留每个组内行的顺序。如果为 False,则组将以与原始 DataFrame 中相同的顺序出现。 |
group_keys | bool, 默认 True 当调用 apply 并且by参数产生类似索引(即转换)结果时,将组键添加到索引以识别片段。默认情况下,当结果的索引(和列)标签与输入匹配时,不包含组键,否则包含组键。 |
observed | 布尔值,默认 False 这仅适用于任何分类分组。如果为 True:仅显示分类分组的观察值。如果为 False:显示分类分组的所有值。 |
dropna | 如果为 True,并且组键包含 NA 值,则 NA 值与行/列一起将被删除。如果为 False,NA 值也将被视为组中的键。 |
返回值:DataFrameGroupBy对象。
import pandas as pd
import numpy as np
data = {
"name":['张一','李二','赵三','李四','王五','张六','王琦'],
"age":[12,11,13,14,17,13,14],
"class":[1,1,2,2,1,3,4]
}
index = ['S1','S2','S3','S4','S5','S6','S7']
df = pd.DataFrame(data,index=index)
df1 = df.reindex(index=index,columns=['name','age','class','math'])
df1.iloc[:4,3] = 80
print(df1)
df1 = df1.iloc[:,[1,2,3]]
dfby = df1.groupby(by='class')
for name, group in dfby:
print(name)
print(group)
-----------------------------------------------------------------
name age class math
S1 张一 12 1 80.0
S2 李二 11 1 80.0
S3 赵三 13 2 80.0
S4 李四 14 2 80.0
S5 王五 17 1 NaN
S6 张六 13 3 NaN
S7 王琦 14 4 NaN
1
age class math
S1 12 1 80.0
S2 11 1 80.0
S5 17 1 NaN
2
age class math
S3 13 2 80.0
S4 14 2 80.0
3
age class math
S6 13 3 NaN
4
age class math
S7 14 4 NaN
1.2 mean()函数
计算组的平均值,排除缺失值。
DataFrameGroupBy.mean(numeric_only = False, engine = None, engine_kwargs = None)
参数说明:
参数名 | 说明 |
numeric_only | 布尔值,默认False。仅包含float,int,boolean 列。 |
engine | str,默认None。 cython :通过 cython 的 C 扩展运行操作。 numba:通过 numba 的 JIT 编译代码运行操作。 None:默认cython 或全局设置 compute.use_numba |
engine_kwargs | 字典,默认 None
|
返回值:Series或DataFrame
import pandas as pd
import numpy as np
data = {
"name":['张一','李二','赵三','李四','王五','张六','王琦'],
"age":[12,11,13,14,17,13,14]
}
index = ['S1','S2','S3','S4','S5','S6','S7']
df = pd.DataFrame(data,index=index)
df1 = df.reindex(index=index,columns=['name','age','math'])
df1.iloc[:4,2] = 80
df2 = df1.iloc[:,[1,2]]
print(df2)
df3 = df2.mean()
print(df3)
------------------------------------------------------------
age math
S1 12 80.0
S2 11 80.0
S3 13 80.0
S4 14 80.0
S5 17 NaN
S6 13 NaN
S7 14 NaN
age 13.428571
math 80.000000
dtype: float64
1.3 Apply()函数
逐组应用函数func,并将结果组合起来。
传递给的函数必须将数据帧作为其第一个参数并返回数据帧、系列或标量。然后将负责将结果组合回单个数据帧或系列中。因此是一种高度灵活的分组方法。
apply虽然是一种非常灵活的方法,但其缺点是使用它可能比使用更具体的方法agg、transform慢很多。 Pandas 提供了多种方法,这些方法比用于特定目的的方法要快得多,因此在使用它们之前请尝试使用它们。
DataFrameGroupBy.apply(func, *args, include_groups=True, **kwargs)
参数说明:
参数名 | 说明 |
func | 一个可调用函数,将数据帧作为其第一个参数,并返回数据帧、序列或标量。此外,可调用对象还可以采用位置参数和关键字参数。 |
include_groups | bool, 默认 True 当为 True 时,如果分组问DataFrame的列,则将尝试将func应用于分组。如果这引发TypeError,则将在排除分组的情况下计算结果。如果为 False,则当应用func时将排除分组。 |
*args、**kwargs | 元组和 dict。要传递给func的可选位置参数和关键字参数。 |
返回值:Series or DataFrame
import pandas as pd
import numpy as np
data = {
"name":['张一','李二','赵三','李四','王五','张六','王琦'],
"age":[12,11,13,14,17,13,14],
"class":[1,1,2,2,1,3,4]
}
index = ['S1','S2','S3','S4','S5','S6','S7']
df = pd.DataFrame(data,index=index)
df1 = df.reindex(index=index,columns=['name','age','class','math'])
df1.iloc[:6,3] = 80
print(df1)
g = df1.groupby('class')
df2 = g[['age','math']].apply(lambda x:x.sum())
print(df2)
---------------------------------------------------------------------
name age class math
S1 张一 12 1 80.0
S2 李二 11 1 80.0
S3 赵三 13 2 80.0
S4 李四 14 2 80.0
S5 王五 17 1 80.0
S6 张六 13 3 80.0
S7 王琦 14 4 NaN
age math
class
1 40.0 240.0
2 27.0 160.0
3 13.0 80.0
4 14.0 0.0
1.4 value_counts()函数
返回一个包含数据框中每个不同行的频率的系列。
DataFrame.value_counts(subset=None, normalize=False,
sort=True, ascending=False,
dropna=True)
参数说明:
参数名 | 说明 |
subset | label or list of labels 计算唯一组合时使用的列。 |
normalize | bool,默认 False 返回比例而不是频率。 |
sort | bool,默认 True True 时按频率排序。当为 False 时,按 DataFrame 列值排序。 |
ascending | 布尔值,默认 False 按升序排序。 |
dropna | bool,默认 True 不包括包含 NA 值的行数。 |
返回值:Series
import pandas as pd
import numpy as np
data = {
"name":['张一','李二','赵三','李四','王五','张六','王琦'],
"age":[12,11,13,14,17,13,14],
"class":[1,1,2,2,1,3,4]
}
index = ['S1','S2','S3','S4','S5','S6','S7']
df = pd.DataFrame(data,index=index)
df1 = df.reindex(index=index,columns=['name','age','class','math'])
df1.iloc[:4,3] = 80
print(df1)
s = df1.value_counts('math',dropna=False)
print(s)
------------------------------------------------------------------
name age class math
S1 张一 12 1 80.0
S2 李二 11 1 80.0
S3 赵三 13 2 80.0
S4 李四 14 2 80.0
S5 王五 17 1 NaN
S6 张六 13 3 NaN
S7 王琦 14 4 NaN
math
80.0 4
NaN 3
Name: count, dtype: int64
2. 合并
2.1 concat()
concat()沿一个轴连接任意数量的Series/DataFrame对象(即行堆叠),同时对其他轴上的索引执行可选的集合逻辑(并集或交集)。像numpy.concatenate 一样, concat()接受同构类型对象的列表或字典并将它们连接起来。
参数说明:
参数名 | 说明 |
DataFrame对象列表 | [df1,df2,df3,...] |
返回值:DataFrame
import pandas as pd
import numpy as np
data1 = {
"name":['张一','李二','赵三','李四','王五','张六','王琦'],
"age":[12,11,13,14,17,13,14],
"class":[1,1,2,2,1,3,4]
}
index = ['S1','S2','S3','S4','S5','S6','S7']
df1 = pd.DataFrame(data1)
print(f'第一个数据组:\n{df1}')
data2 = {
'name':['赵一', '赵二', '赵三', '赵四', '赵五', '赵六', '赵七',],
'age':np.random.randint(12, high=21, size=7),
'class':np.random.randint(1, high=4, size=7),
}
df2 = pd.DataFrame(data2)
print(f'第二个数据组:\n{df2}')
df = pd.concat([df1, df2])
print(f'合并后数据组:\n{df}')
-----------------------------------------------------------------
~/Python python concat.py
第一个数据组:
name age class
0 张一 12 1
1 李二 11 1
2 赵三 13 2
3 李四 14 2
4 王五 17 1
5 张六 13 3
6 王琦 14 4
第二个数据组:
name age class
0 赵一 13 2
1 赵二 13 3
2 赵三 17 2
3 赵四 15 3
4 赵五 16 3
5 赵六 17 3
6 赵七 14 3
合并后数据组:
name age class
0 张一 12 1
1 李二 11 1
2 赵三 13 2
3 李四 14 2
4 王五 17 1
5 张六 13 3
6 王琦 14 4
0 赵一 13 2
1 赵二 13 3
2 赵三 17 2
3 赵四 15 3
4 赵五 16 3
5 赵六 17 3
6 赵七 14 3
2.2 数据库风格连接 join
join可以使用join()或merge()来执行。默认情况下,join()将连接其索引上的DataFrames。每个方法都有参数,允许您指定要执行的联接类型(LEFT、RIGHT、INNER、FULL)或要联接的列(列名或索引)。
如果两个键列都包含键为null值的行,则这些行将相互匹配。这与通常的SQL联接行为不同,可能会导致意外的结果。
2.2.1 merge()
pandas.merge(left, right, how='inner', on=None,
left_on=None, right_on=None, left_index=False,
right_index=False, sort=False, suffixes=('_x', '_y'),
copy=None, indicator=False, validate=None)
参数说明:
参数名 | 说明 |
left | DataFrame or named Series |
right | DataFrame or named Series |
how | {‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’}, default ‘inner’ |
on | label or list 要连接的列或索引级别名称。这些必须在两个 DataFrame 中找到。如果on为 None 并且不合并索引,则默认为两个 DataFrame 中列的交集。 |
left_on | label or list 要连接到左侧 DataFrame 的列或索引级别名称。也可以是左侧 DataFrame 长度的数组或数组列表。这些数组被视为列。 |
right_on | label or list 要连接到右侧 DataFrame 中的列或索引级别名称。也可以是正确 DataFrame 长度的数组或数组列表。这些数组被视为列。 |
left_index | bool, 默认 False 使用左侧 DataFrame 的索引作为连接键。如果它是 MultiIndex,则其他 DataFrame 中的键数(索引或列数)必须与级别数匹配。 |
right_index | bool, 默认 False 使用右侧 DataFrame 的索引作为连接键。如果它是 MultiIndex,则其他 DataFrame 中的键数(索引或列数)必须与级别数匹配。 |
sort | bool,默认 False 在结果 DataFrame 中按字典顺序对连接键进行排序。如果为 False,则连接键的顺序取决于连接类型(how 关键字)。 |
suffixes | 列表,默认为(“_x”,“_y”) 长度为 2 的序列,其中每个元素都可以是一个字符串,指示分别添加到左侧和右侧重叠列名称的后缀 。传递None值而不是字符串,以指示左侧或 右侧的列名称应保持原样,不带后缀。至少其中一个值不得为 None。 |
copy | bool,默认 True 如果为 False,请尽可能避免复制 |
indicator | bool 或 str,默认 False 如果为 True,则向输出 DataFrame 添加一列名为“_merge”的列,其中包含有关每行源的信息。可以通过提供字符串参数来为该列指定不同的名称。该列将具有分类类型,对于合并键仅出现在左侧 DataFrame 中的观察,值为“left_only”;对于合并键仅出现在右侧 DataFrame 中的观察,值为“right_only”;如果观察的合并键为“both”在两个 DataFrame 中都可以找到。 |
validate | str,可选 如果指定,则检查合并是否属于指定类型。
|
返回值:两个合并对象的DataFrame
import pandas as pd
import numpy as np
data1 = {
"id":[1,2,3,4,5,6],
"age":np.random.randint(15, 20, size=6),
"class":np.random.randint(1, 4, size=6)
}
df1 = pd.DataFrame(data1)
data2 = {
"id": [1, 2, 4, 5, 6],
"name": ["John", "Smith", "Jesse", "Neal", "Bob"],
}
df2 = pd.DataFrame(data2)
df_left = pd.merge(df1, df2, on="id", how="left")
df_right = pd.merge(df1, df2, on="id", how="right")
df_inner = pd.merge(df1, df2, on="id", how="inner")
df_outer = pd.merge(df1, df2, on="id", how="outer")
df_cross = pd.merge(df1, df2, how="cross")
print(f'左连接结果:\n{df_left}')
print(f'右连接结果:\n{df_right}')
print(f'内连接结果:\n{df_inner}')
print(f'外连接结果:\n{df_outer}')
print(f'笛卡尔积结果:\n{df_cross}')
----------------------------------------------------
左连接结果:
id age class name
0 1 18 2 John
1 2 15 2 Smith
2 3 15 2 NaN
3 4 15 1 Jesse
4 5 18 2 Neal
5 6 19 2 Bob
右连接结果:
id age class name
0 1 18 2 John
1 2 15 2 Smith
2 4 15 1 Jesse
3 5 18 2 Neal
4 6 19 2 Bob
内连接结果:
id age class name
0 1 18 2 John
1 2 15 2 Smith
2 4 15 1 Jesse
3 5 18 2 Neal
4 6 19 2 Bob
外连接结果:
id age class name
0 1 18 2 John
1 2 15 2 Smith
2 3 15 2 NaN
3 4 15 1 Jesse
4 5 18 2 Neal
5 6 19 2 Bob
笛卡尔积结果:
id_x age class id_y name
0 1 18 2 1 John
1 1 18 2 2 Smith
2 1 18 2 4 Jesse
3 1 18 2 5 Neal
4 1 18 2 6 Bob
5 2 15 2 1 John
6 2 15 2 2 Smith
7 2 15 2 4 Jesse
8 2 15 2 5 Neal
9 2 15 2 6 Bob
10 3 15 2 1 John
11 3 15 2 2 Smith
12 3 15 2 4 Jesse
13 3 15 2 5 Neal
14 3 15 2 6 Bob
15 4 15 1 1 John
16 4 15 1 2 Smith
17 4 15 1 4 Jesse
18 4 15 1 5 Neal
19 4 15 1 6 Bob
20 5 18 2 1 John
21 5 18 2 2 Smith
22 5 18 2 4 Jesse
23 5 18 2 5 Neal
24 5 18 2 6 Bob
25 6 19 2 1 John
26 6 19 2 2 Smith
27 6 19 2 4 Jesse
28 6 19 2 5 Neal
29 6 19 2 6 Bob
2.2.2 join()
DataFrame.join(other, on=None, how='left',
lsuffix='', rsuffix='', sort=False,
validate=None)
参数说明:
参数名 | 说明 |
other | DataFrame、Series 或包含它们任意组合的列表。 索引应该类似于这一列中的一列。如果传递了 Series,则必须设置其 name 属性,该属性将用作生成的连接 DataFrame 中的列名称。 |
on | str、str 列表或类似数组上,可选 调用者中要连接到other中的索引的列或索引级别名称,否则连接索引上的索引。如果给定多个值,则另一个DataFrame 必须具有 MultiIndex。如果调用 DataFrame 中尚未包含数组,则可以传递数组作为连接键。类似于 Excel VLOOKUP 运算。 |
how | {'left', 'right', 'outer', 'inner', 'cross'}, 默认'left' 如何处理两个对象的操作。
|
lsuffix | str,默认 '' 从左框架的重叠列使用的后缀。 |
rsuffix | str,默认 '' 从右框架的重叠列使用的后缀。 |
sort | bool,默认 False 通过连接键按字典顺序对结果 DataFrame 进行排序。如果为 False,则连接键的顺序取决于连接类型(how 关键字)。 |
validate | str,可选 如果指定,则检查连接是否属于指定类型。
|
返回值:数据框,包含来自调用方和其他方的列的数据框。
import pandas as pd
import numpy as np
data1 = {
"id":[1,2,3,4,5,6],
"age":np.random.randint(15, 20, size=6),
"class":np.random.randint(1, 4, size=6)
}
df1 = pd.DataFrame(data1)
data2 = {
"name": ["John", "Smith", "Jesse", "Neal", "Bob"],
}
df2 = pd.DataFrame(data2)
df_left = df1.join(df2, how="left", rsuffix="_right", lsuffix="_left")
df_right = df1.join(df2, how="right", rsuffix="_right", lsuffix="_left")
df_inner = df1.join(df2, how="inner", rsuffix="_right", lsuffix="_left")
df_outer = df1.join(df2, how="outer", rsuffix="_right", lsuffix="_left")
df_cross = df1.join(df2, how="cross", rsuffix="_right", lsuffix="_left")
print(f'左连接结果:\n{df_left}')
print(f'右连接结果:\n{df_right}')
print(f'内连接结果:\n{df_inner}')
print(f'外连接结果:\n{df_outer}')
print(f'笛卡尔积结果:\n{df_cross}')
---------------------------------------------------------
左连接结果:
id age class name
0 1 16 3 John
1 2 19 1 Smith
2 3 16 3 Jesse
3 4 19 1 Neal
4 5 16 3 Bob
5 6 19 1 NaN
右连接结果:
id age class name
0 1 16 3 John
1 2 19 1 Smith
2 3 16 3 Jesse
3 4 19 1 Neal
4 5 16 3 Bob
内连接结果:
id age class name
0 1 16 3 John
1 2 19 1 Smith
2 3 16 3 Jesse
3 4 19 1 Neal
4 5 16 3 Bob
外连接结果:
id age class name
0 1 16 3 John
1 2 19 1 Smith
2 3 16 3 Jesse
3 4 19 1 Neal
4 5 16 3 Bob
5 6 19 1 NaN
笛卡尔积结果:
id age class name
0 1 16 3 John
1 1 16 3 Smith
2 1 16 3 Jesse
3 1 16 3 Neal
4 1 16 3 Bob
5 2 19 1 John
6 2 19 1 Smith
7 2 19 1 Jesse
8 2 19 1 Neal
9 2 19 1 Bob
10 3 16 3 John
11 3 16 3 Smith
12 3 16 3 Jesse
13 3 16 3 Neal
14 3 16 3 Bob
15 4 19 1 John
16 4 19 1 Smith
17 4 19 1 Jesse
18 4 19 1 Neal
19 4 19 1 Bob
20 5 16 3 John
21 5 16 3 Smith
22 5 16 3 Jesse
23 5 16 3 Neal
24 5 16 3 Bob
25 6 19 1 John
26 6 19 1 Smith
27 6 19 1 Jesse
28 6 19 1 Neal
29 6 19 1 Bob