Python 环境加载中…

挑出想要的数据

3 道练习题·预计 45 分钟·做对一题解锁下一段

完整通读本章 →

教学 01 / 08· 已读

前言

上一章,咱们把记账本这张表看清楚了:一千多行、5 列,每一列是什么类型,心里都有数了。

可是真要回答问题的时候,往往用不着整张表。比如「看病一年花了多少?」,只要医疗那几行就够了;「哪几笔花得最多?」,只要金额大的那几行;「每天的早饭吃了些什么?」,只要名称这一列里的一部分。

所以这一章,就来学怎么从一张大表里,把想要的那部分挑出来。挑法主要有三种:按列挑、按位置挑、按条件挑。为什么要专门花一章来学呢?因为这是 pandas 里用得最多的本事,后面每一章都离不开它。

学这一章之前,需要先学完 数据分析课第 2 章 。

目录

这一章会学到:

  • 一、按列挑——一列、几列,以及去掉不要的列
  • 二、按位置挑——iloc 和 loc
  • 三、按条件挑——一串 True 和 False
  • 四、好几个条件——& 、| 、~ 和 isin()
  • 五、常见坑
  • 六、自己查一次文档——用 between() 挑出一个范围
  • 七、小结与回看

学完这一章,脑子里冒出一个问题,你就能把回答它所需要的那部分数据,从表里干干净净地挑出来。

教学 02 / 08· 已读

一、按列挑

先从最简单的按列挑说起。上一章已经见过:方括号里写一个列名,就能取出一列;写一个列名的列表,就能取出好几列。不过这里面有一个容易忽略的区别,先运行下面的代码看看:

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
print(type(ledger['item']))
print(type(ledger[['item']]))

输出的结果:

文本
<class 'pandas.core.series.Series'>
<class 'pandas.core.frame.DataFrame'>

同样是 item 这一列,用一层方括号,得到的是 Series;用两层方括号,得到的却是 DataFrame,也就是一张只有一列的表。

为什么要分得这么清楚呢?因为两者能做的事不一样:

  • Series 是一串值,可以直接 sum() 、unique() 。
  • DataFrame 是一张表,打印出来带着列名,还能接着挑行、挑列。

所以,只想要一串值,就用一层方括号;想要的还是一张表,就用两层。

好几列一起取的时候,还有一个小细节:列的顺序,是按你写的顺序来的。

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
print(ledger[['cost', 'item', 'date']].head(3))

输出的结果:

文本
     cost      item        date
0  2500.0      房租  2026-01-01
1   156.0  水电燃气  2026-01-01
2    13.0      早饭  2026-01-01

cost 写在最前面,打印出来它就排在了第一列。

那要是想要的列很多,不要的只有一两列呢?一个一个地写想要的列,就太麻烦了。这时候反过来,只写不要的那几列更省事,用 drop(columns=[...]) :

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
no_payment = ledger.drop(columns=['payment'])
print(list(no_payment.columns))
print(ledger.shape)

输出的结果:

文本
['date', 'item', 'category', 'cost']
(1354, 5)

先看第一行:payment 这一列已经去掉了。再留意第二行:ledger 还是 5 列。这是因为 drop() 不会改动原来的表,而是返回一张新表。pandas 里大部分方法都是这样,所以要保留结果,就得用一个变量把它接住,比如这里的 no_payment 。

教学 03 / 08

二、按位置挑

列会挑了,那行该怎么挑呢?

最直接的办法,是按位置挑,也就是说「我要第几行」。这时候用 iloc ,方括号里写位置。和列表的下标一样,位置也是从 0 开始数的:

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
print(ledger.iloc[0])

输出的结果:

文本
date        2026-01-01
item              房租
category          居住
cost            2500.0
payment         银行卡
Name: 0, dtype: object

取出一行,得到的也是一个 Series。只不过这回,是把横着的一行竖过来放:左边是列名,右边是这一行的值。最下面的 Name: 0 告诉你,这是行号为 0 的那一行。

一次只取一行,不够用怎么办?可以用切片,一次取好几行。切片的规则也和列表一样,不包括结尾:

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
print(ledger.iloc[9:12])
print(ledger.iloc[-2:])

输出的结果:

文本
          date  item category  cost payment
9   2026-01-02  地铁     交通   6.5    微信
10  2026-01-02  零食     餐饮  12.5  支付宝
11  2026-01-03  午饭     餐饮  27.0  支付宝
            date  item category  cost payment
1352  2026-12-31  地铁     交通   4.0    微信
1353  2026-12-31  零食     餐饮   9.5    微信

iloc[9:12] 取的是位置 9、10、11 这三行,不包括 12。iloc[-2:] 取的是最后两行,因为负数是从后往前数的,这一点也和列表一样。

除了 iloc ,还有一个 loc 。它和 iloc 有什么不同呢?loc 是按行的标签来挑,也就是最左边那一列行号。而且它还能同时用列名挑列:逗号前面写行,逗号后面写列。

Python· 可在网页运行
import pandas as pd

ledger = pd.read_csv('ledger_2026.csv')
print(ledger.loc[0, 'item'])
print(ledger.loc[9:11, ['item', 'cost']])

输出的结果:

文本
房租
    item  cost
9   地铁   6.5
10  零食  12.5
11  午饭  27.0

来看看这两行各取出了什么:

  • loc[0, 'item'] 是行号为 0 的那一行、item 那一列,正好就是一个值:房租。
  • loc[9:11, ...] 取出了 9、10、11 这三行。注意,它包括结尾的 11,这一点和 iloc 不一样。

把两者放在一起,比一比:

ilocloc
按什么挑位置:第几行、第几列标签:行号、列名
写法ledger.iloc[0] 、ledger.iloc[9:12]ledger.loc[0, 'item'] 、ledger.loc[9:11, ['item', 'cost']]
切片包不包括结尾不包括,和列表一样包括

看到这里,有的童鞋可能会觉得:行号和位置不都是 0、1、2 吗,两者好像也差不多?没错,眼下行号和位置是一回事,所以看起来差不多。可是下一节按条件挑完以后,行号就不再是 0、1、2 这样连着的了,到时候区别就出来了。

在那之前,先做一道练习:挑出几行几列,顺便留意一下切片的结尾包不包括。

练习 1 / 3挑出几行几列题目有问题?

读进记账本,挑出行号为 100、101、102 的这三行,只要 date 、item 、cost 三列,打印出来。用 loc 或者 iloc 都可以,留意切片的结尾包不包括。

运行后的输出应该是:

文本
           date  item  cost
100  2026-01-26  地铁   5.5
101  2026-01-27  早饭   7.0
102  2026-01-27  午饭  32.5
main.py
可编辑
做对当前题解锁下一段 ·03

推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai

学习目录