在 理解DataFrame中的Merge操作 中,我们给大家介绍了 DataFrame 的 Merge 函数基本用法。通常,我们是对两个或多个 DataFrame 进行 merge ,但如果源数据一个是 DataFrame ,另一个是 Series, 我们还能进行合并吗?
案例构造
假设有一个表示用户账号信息的 DataFrame, 如下:
1 | acc_id acc_name |
acc_id, acc_name 分别表示用户id和用户名称。
还有另外一个 DataFrame 表示某个时间端内用户在系统中使用功能的日志, 如下:
1 | acc_id func_id |
acc_id是用户id, func_id是功能编号(比如: 1代表用户登录,2代表用户浏览商品 等等), 总数有100条。
现在,我们想知道在这100条中,每个用户分别占了多少条? 当然,这其实是一个分组统计数量的问题,如果是在SQL数据库中,我们的方法是写类似的SQL: select key, count(1) from …. group by key
在 pandas 的 DataFrame 中,我们只需要通过一个切片和要给函数也可以很简单的完成,代码如下:
1 | import random |
运行程序,输出为:
1 | 1 35 |
可以看到,我们实际上是对 DataFrame f2进行了一个切片 f2[‘acc_id’], 得到一个序列(Series),然后再执行序列的函数 value_counts 进行统计的
DataFrame 与 Series 进行 Merge
如果我们希望在最终的结果中,能看到用户的名称,而不是只有用户的id, 这就需要我们将 f1 (DataFrame) 和 s_counts 进行合并,按照 merge 的语法,我们使用如下代码尝试合并:
1 | f4 = pd.merge(f1, s_counts) |
运行程序,系统输出:
1 | Empty DataFrame |
可以看出,合并实际没有成功。
通过对 DataFrame 合并规则的分析可以知道, Merge操作是需要有列名间存在对应关系为前提的,但我们通过 value_counts 函数最终生成的序列 (Series) 实际上是没有列名的,应该Merge函数也没法找到合并的条件。解决的方法就是为序列 (Series) 指定列名和索引名,注意不用忘了给索引名。其实每个序列 (Series) 都可以看作是一个只有两列的二维表,一列是索引,一列是数据。
回到刚才的例子, DataFrame 执行切片操作 [‘acc_id’] 以后,拿到其实就是一个以’acc_id’为索引,以func_id为数据的序列,只是我们没有对这个序列的索引和数据进行命名。
知道了原因,那就简单了,解决方法就是:在合并前对Series的索引和数据列进行命名,在合并前加入下面的代码:
1 | s_counts.index.name = 'acc_id' |
执行程序,这个时候我们会得到一个 “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 | acc_id acc_name func_counts |
最后,贴出完整的示例程序:
1 | import random |
通过这个示例,希望大家一方面能知道如何 Merge 一个 DataFrame 和一个 Series, 更重要的一方面是希望能够更深入的认识序列 (Series)这种数据结构的特性。