DataFrame 合并(Merge) Series

理解DataFrame中的Merge操作 中,我们给大家介绍了 DataFrame 的 Merge 函数基本用法。通常,我们是对两个或多个 DataFrame 进行 merge ,但如果源数据一个是 DataFrame ,另一个是 Series, 我们还能进行合并吗?

案例构造

假设有一个表示用户账号信息的 DataFrame, 如下:

1
2
3
4
5
   acc_id acc_name
0 1 张三
1 2 李四
2 3 王二麻子
3 4 奥特曼

acc_id, acc_name 分别表示用户id和用户名称。

还有另外一个 DataFrame 表示某个时间端内用户在系统中使用功能的日志, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    acc_id  func_id
0 3 6
1 3 10
2 1 5
3 2 2
4 3 2
5 2 5
6 4 8
.. ... ...
94 4 8
95 4 7
96 4 2
97 1 8
98 2 8
99 3 5

acc_id是用户id, func_id是功能编号(比如: 1代表用户登录,2代表用户浏览商品 等等), 总数有100条。

现在,我们想知道在这100条中,每个用户分别占了多少条? 当然,这其实是一个分组统计数量的问题,如果是在SQL数据库中,我们的方法是写类似的SQL: select key, count(1) from …. group by key
在 pandas 的 DataFrame 中,我们只需要通过一个切片和要给函数也可以很简单的完成,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
import random
import pandas as pd
from pandas import DataFrame

f1 = DataFrame({'acc_id': [1, 2, 3, 4],
'acc_name': ['张三', '李四', '王二麻子', '奥特曼']})

f2 = DataFrame({'acc_id': [ x for x in [random.randint(1, 4) for i in range(100)]],
'func_id': [ x for x in [random.randint(1, 10) for i in range(100)]] })

s_counts = f2['acc_id'].value_counts()
print (s_counts)

运行程序,输出为:

1
2
3
4
5
1    35
4 29
2 20
3 16
Name: acc_id, dtype: int64

可以看到,我们实际上是对 DataFrame f2进行了一个切片 f2[‘acc_id’], 得到一个序列(Series),然后再执行序列的函数 value_counts 进行统计的

DataFrame 与 Series 进行 Merge

如果我们希望在最终的结果中,能看到用户的名称,而不是只有用户的id, 这就需要我们将 f1 (DataFrame) 和 s_counts 进行合并,按照 merge 的语法,我们使用如下代码尝试合并:

1
2
f4 = pd.merge(f1, s_counts)
print (f4)

运行程序,系统输出:

1
2
3
Empty DataFrame
Columns: [acc_id, acc_name]
Index: []

可以看出,合并实际没有成功。

通过对 DataFrame 合并规则的分析可以知道, Merge操作是需要有列名间存在对应关系为前提的,但我们通过 value_counts 函数最终生成的序列 (Series) 实际上是没有列名的,应该Merge函数也没法找到合并的条件。解决的方法就是为序列 (Series) 指定列名和索引名,注意不用忘了给索引名。其实每个序列 (Series) 都可以看作是一个只有两列的二维表,一列是索引,一列是数据。
回到刚才的例子, DataFrame 执行切片操作 [‘acc_id’] 以后,拿到其实就是一个以’acc_id’为索引,以func_id为数据的序列,只是我们没有对这个序列的索引和数据进行命名。
知道了原因,那就简单了,解决方法就是:在合并前对Series的索引和数据列进行命名,在合并前加入下面的代码:

1
2
s_counts.index.name = 'acc_id'
s_counts.name = 'func_counts'

执行程序,这个时候我们会得到一个 “pandas.errors.MergeError: No common columns to perform merge on. Merge options: left_on=None, right_on=None, left_index=False, right_index=False” 的错误。 原来是因为merge函数在合并 DataFrame 和 Series 时,需要显示的指明关联的键是什么,修改merge的参数如下就可以了:

1
f4 = pd.merge(f1, s_counts, on='acc_id')

运行程序,系统输出了希望的结果:

1
2
3
4
5
   acc_id acc_name  func_counts
0 1 张三 14
1 2 李四 25
2 3 王二麻子 37
3 4 奥特曼 24

最后,贴出完整的示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import random
import pandas as pd
from pandas import DataFrame

f1 = DataFrame({'acc_id': [1, 2, 3, 4],
'acc_name': ['张三', '李四', '王二麻子', '奥特曼']})

f2 = DataFrame({'acc_id': [ x for x in [random.randint(1, 4) for i in range(100)]],
'func_id': [ x for x in [random.randint(1, 10) for i in range(100)]] })

s_counts = f2['acc_id'].value_counts()

s_counts.index.name = 'acc_id'
s_counts.name = 'func_counts'

f4 = pd.merge(f1, s_counts, on='acc_id')

print (f4)

通过这个示例,希望大家一方面能知道如何 Merge 一个 DataFrame 和一个 Series, 更重要的一方面是希望能够更深入的认识序列 (Series)这种数据结构的特性。

本文标题:DataFrame 合并(Merge) Series

文章作者:晨星

发布时间:2019年06月24日 - 17:06

最后更新:2020年05月28日 - 16:05

原始链接:https://www.mls-tech.info/python/python-pandas-merge-series/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。