把几张表拼起来
3 道练习题·预计 45 分钟·做对一题解锁下一段
前言
前面几章,每次分析的都只是一张表。可真实的数据,常常是分散在好几张表里的。
两点书店的数据就是这样,分成了两张表。books.csv 是书目,记着每本书的书名、作者、类别、价格。book_reviews.csv 是读者的评分,一条评分占一行,只记了是给哪个编号的书、打了几分、哪天打的。
那么,要是想知道「哪一类书评分最高」呢?这时候两张表缺一不可:评分在一张表里,类别却在另一张表里。所以,得先把它们合并起来。
这一章就来学两种合并的办法:一种是按某一列「对上号」,左右拼起来;另一种是把几张一样的表,上下接起来。
学这一章之前,需要先学完 数据分析课第 6 章 。
目录
这一章会学到:
- 一、两张表怎么对上号——认识「键」
- 二、左右拼起来——
merge() - 三、对不上号的行去哪儿了——
how参数 - 四、上下接起来——
pd.concat() - 五、常见坑
- 六、自己查一次文档——用
indicator看清每一行从哪儿来 - 七、小结与回看
学完这一章,数据分散在几张表里也不用怕了:你能先把它们拼成一张,再接着用前面学的本事去分析。
一、两张表怎么对上号
两张表要合并,首先得知道它们靠什么连在一起。咱们先看看评分表里都记了些什么:
import pandas as pd
reviews = pd.read_csv('book_reviews.csv')
print(reviews.shape)
print(reviews.head(3))输出的结果:
(834, 4)
review_id book_id score date
0 1 111 4 2025-01-01
1 2 49 2 2025-01-02
2 3 106 4 2025-01-02可以看到,评分表一共有 834 条评分。每一条里,和书有关的只有一个 book_id ,也就是书的编号。比如第一条评分,是给 111 号书的,打了 4 分。那 111 号书叫什么、是什么类别呢?这张表里可就没有了。
书名和类别,都记在书目表里。再从书目表里挑三列出来看看:
import pandas as pd
books = pd.read_csv('books.csv')
print(books[['id', 'title', 'category']].head(3))输出的结果:
id title category
0 1 轻松玩转自动化 编程
1 2 小账本里的通货膨胀 经济
2 3 早起养花 生活两边对比一下就会发现:书目表里的 id ,就是评分表里的 book_id 。两张表就是靠这个编号对上号的。评分表说「111 号书打了 4 分」,那就去书目表里找 id 是 111 的那一行,一看就知道是哪本书了。
像这样用来对号的列,叫做键(key)。它就像身份证号一样,一个编号只对应一本书。
看到这里,很多童鞋可能会问:「为什么不在评分表里直接写上书名呢?」因为一本书有好几条评分,要是书名、作者、类别、价格每条都写一遍,就太浪费了;而且万一哪本书改了价格,还得把它所有的评分都改一遍。所以,数据常常分成几张表,各管各的,再用键连在一起。等到要分析的时候,再把它们合并起来。
那么,具体怎么合并呢?下一节就来动手。
二、左右拼起来
按键把两张表左右拼起来,用的是 merge() 。不过,这两张表里键的列名不一样:评分表里叫 book_id ,书目表里叫 id 。所以要分别告诉它:left_on 写左边那张表的列名,right_on 写右边那张表的列名:
import pandas as pd
books = pd.read_csv('books.csv')
reviews = pd.read_csv('book_reviews.csv')
merged = reviews.merge(books, left_on='book_id', right_on='id')
print(merged.shape)
print(merged[['review_id', 'book_id', 'title', 'category', 'score']].head(3))输出的结果:
(834, 14)
review_id book_id title category score
0 1 111 小账本里的保险 经济 4
1 2 49 月亮的冒险 童书 2
2 3 106 一个人的厨房 生活 4读这行合并的代码,先要分清谁在左、谁在右。reviews.merge(books, ...) 里,reviews 在左,books 在右。合并的时候,每一条评分都会拿着自己的 book_id ,去书目表里找到 id 一样的那一行,再把那一行拼到自己的右边。
再看输出的第一行。拼完以后还是 834 行,因为仍然是每条评分占一行;列却变成了 14 列,也就是评分表的 4 列,加上书目表的 10 列。这样一来,每条评分旁边,就都有了书名和类别。
有了类别,前言里那个问题「哪一类书评分最高」,就能回答了。用的还是第 6 章的老本事,按类别分组:
import pandas as pd
books = pd.read_csv('books.csv')
reviews = pd.read_csv('book_reviews.csv')
merged = reviews.merge(books, left_on='book_id', right_on='id')
print(merged.groupby('category')['score'].agg(['count', 'mean']).round(2).sort_values('mean', ascending=False))输出的结果:
count mean
category
设计 107 3.83
编程 107 3.68
小说 100 3.59
童书 88 3.50
经济 106 3.50
科普 108 3.38
历史 100 3.36
生活 118 3.25从结果看,设计类的书评分最高,平均 3.83 分;生活类收到的评分最多,平均分却是最低的。
所以说,合并只是一个开头。表拼好了以后,筛选、分组、排序,前几章学的本事都能接着用。
不过,这回每一条评分都对上了号,拼完一行也没少。要是有的行对不上号,又会怎么样呢?下一节就来看看。在那之前,先做一道练习:给评分配上书名。
读进两张表,把评分表和书目表按书的编号合并,然后只取 review_id 、title 、score 三列,打印前 5 行。
运行后的输出应该是:
review_id title score
0 1 小账本里的保险 4
1 2 月亮的冒险 2
2 3 一个人的厨房 4
3 4 好好收纳 4
4 5 小账本里的通货膨胀 4推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai