返回首页

Roadmap
更新于 2026年10月27日 全文 1374 字未阅读

第 1.2 节 编程练习#

预计学习时长: 40 分钟

练习方式: 建议新建一个 Jupyter Notebook,把下面的数据准备代码抄进去,然后每题独立完成。先写,写不出再展开答案——直接看答案的练习几乎没有效果。

本课程使用的 Pandas 版本是 '3.1.0'

本小节示例代码文件: 。

准备:先把数据建好#

这 5 道题都用同一张订单表。在 Notebook 的第一个单元格执行:

import pandas as pd

data = {
    "订单号":   [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008],
    "下单日期": ["2024-01-05", "2024-01-08", "2024-01-12", "2024-02-03",
                 "2024-02-15", "2024-03-02", "2024-03-20", "2024-04-08"],
    "城市":     ["北京", "上海", "北京", "广州", "上海", "北京", "深圳", "广州"],
    "商品":     ["手机", "电脑", "耳机", "手机", "键盘", "显示器", "耳机", "手机"],
    "销量":     [2, 1, 3, 2, 5, 1, 4, 2],
    "单价":     [3999.0, 7999.0, 599.0, 3999.0, 299.0, 1299.0, 599.0, 3999.0],
    "金额":     [7998.0, 7999.0, 1797.0, 7998.0, 1495.0, 1299.0, 2396.0, 7998.0],
    "客户评分": [4.5, 4.0, 4.8, 3.9, 4.2, 4.6, 4.1, 4.9],
}

df = pd.DataFrame(data)

练习 1:从字典创建 DataFrame#

题目: 上面已经建好了 df。现在请你自己动手,用一个新的字典 student_data 创建一个学生信息表,包含 3 列:

  • 姓名:["小明", "小红", "小华"]
  • 年龄:[18, 19, 20]
  • 城市:["北京", "上海", "广州"]

然后把它存到变量 students,并打印出来。

要求: 不许直接抄上面的 data,自己敲一遍。

点击查看参考答案
student_data = {
    "姓名": ["小明", "小红", "小华"],
    "年龄": [18, 19, 20],
    "城市": ["北京", "上海", "广州"],
}

students = pd.DataFrame(student_data)
print(students)

输出:

   姓名  年龄  城市
0  小明   18  北京
1  小红   19  上海
2  小华   20  广州

要点: 字典的键 = 列名,字典的值 = 这一列的数据(必须是一个列表)。3 个键就是 3 列,值的长度 3 就是 3 行。


练习 2:获取 DataFrame 行和列数#

题目: 用三种方式分别拿到 df 的行数和列数:

  1. 用 df.shape 一次性拿到;

  2. 用 len() 拿行数;

  3. 用 df.shape[0] 和 df.shape[1] 分别拿。

把三个结果都 print 出来,对照一下它们是不是一致。

附加要求: 再创建一个只有 0 行 0 列的空表 empty = pd.DataFrame(),打印它的 shape。

点击查看参考答案
# 方式 1:一次性拿到
print(df.shape)        # (8, 8)

# 方式 2:len() 拿行数
print(len(df))         # 8

# 方式 3:分别取
print(df.shape[0])     # 8  行数
print(df.shape[1])     # 8  列数

# 空表
empty = pd.DataFrame()
print(empty.shape)     # (0, 0)

要点: df.shape 返回的是元组,顺序是**(行数,列数),别看反了。len(df) 对 DataFrame 来说返回的是行数**,因为它先问「这张表有几条记录」。


练习 3:指定列创建新 DataFrame#

题目: 已知 df 有 8 列。请完成下面 4 个取列操作,并分别打印出结果的 type:

  1. 取出「城市」这一列;

  2. 取出「城市」和「商品」两列;

  3. 取出「订单号」「城市」「商品」「销量」四列,存到变量 order_info;

  4. 取出「客户评分」这一列,但要让它保持 DataFrame 类型(提示:想想双层方括号)。

思考题: 为什么第 1 题和第 4 题写的代码看起来只差一层方括号,结果类型却不一样?

点击查看参考答案
# 1. 取一列 → Series
cities = df["城市"]
print(type(cities))    # <class 'pandas.Series'>

# 2. 取两列 → DataFrame
two_cols = df[["城市", "商品"]]
print(type(two_cols))  # <class 'pandas.DataFrame'>

# 3. 取四列
order_info = df[["订单号", "城市", "商品", "销量"]]
print(order_info)

# 4. 单列但保持 DataFrame
scores = df[["客户评分"]]
print(type(scores))    # <class 'pandas.core.frame.DataFrame'>

输出(order_info):

     订单号  城市  商品  销量
0    1001  北京  手机   2
1    1002  上海  电脑   1
2    1003  北京  耳机   3
3    1004  广州  手机   2
4    1005  上海  键盘   5
5    1006  北京  显示器   1
6    1007  深圳  耳机   4
7    1008  广州  手机   2

要点:

  • df["城市"] → 单层方括号 → Series
  • df[["城市"]] → 双层方括号 → DataFrame

内层的 ["城市"] 是一个 Python 列表,Pandas 看到「列表」就理解为「我要这几列」,所以给回一张表;看到「字符串」就理解为「我要这一列」,给回一个 Series。


练习 4:查看各列的数据类型#

题目: 完成下面 4 个操作:

  1. 打印整张表每一列的数据类型;

  2. 只打印「销量」这一列的类型;

  3. 打印「城市」这一列的类型;

  4. 打印「客户评分」这一列的类型。

思考题: 第 2、3、4 题的答案分别是什么?为什么「销量」和另外两个不一样?

点击查看参考答案
# 1. 所有列的类型
print(df.dtypes)

输出:

订单号       int64
下单日期        str
城市          str
商品          str
销量        int64
单价      float64
金额      float64
客户评分    float64
dtype: object
# 2、3、4:单列的类型
print(df["销量"].dtype)      # int64
print(df["城市"].dtype)      # str
print(df["客户评分"].dtype)  # float64

要点:

  • 「销量」是 int64:因为写的是 2、1、3 这些整数,全是整数就是 int;
  • 「客户评分」是 float64:因为写的是 4.5、4.0 这种带小数点的数;
  • 「城市」是 str:装的是字符串。

一个小坑 就算你写 4.0 而不是 4,它还是 float64——Python 里 4.0 就是浮点数。所以想让一列保持整数类型,写的时候不要带小数点。


练习 5:查看数据前 5 行和后 3 行#

题目: 完成下面 4 个操作:

  1. 查看 df 的前 5 行(默认值);
  2. 查看 df 的前 3 行;
  3. 查看 df 的后 3 行;
  4. 打印「后 3 行」这个结果的行数和列数。

思考题: 第 4 题的结果是多少?如果和你想的不一样,去 df.shape 那里找原因。

点击查看参考答案
# 1. 前 5 行(默认)
df.head()

# 2. 前 3 行
df.head(3)

# 3. 后 3 行
df.tail(3)

# 4. 后 3 行的形状
print(df.tail(3).shape)     # (3, 8)

df.tail(3) 的输出:

     订单号        下单日期  城市  商品  销量      单价      金额  客户评分
5    1006  2024-03-02  北京  显示器   1  1299.0   1299.0   4.6
6    1007  2024-03-20  深圳  耳机   4   599.0   2396.0   4.1
7    1008  2024-04-08  广州  手机   2  3999.0   7998.0   4.9

要点: tail(3) 切出来的表是 3 行 8 列——行数被截断了,但列数不变。

对比一下 df.shape 是 (8, 8),你就明白 head/tail 切的是行,不是列。

顺便注意 tail(3) 输出的行索引还是 5、6、7,没有重新从 0 开始编号。这是 Pandas 的一个特性(切片保留原索引),第 2 章讲 reset_index() 时会再碰到它。


加分练习#

做完上面 5 题,如果你还有兴趣,试试这个:

题目: 不看答案,输出一份「数据体检报告」,包含:

  • 表的规模(几行几列);
  • 每列的类型;
  • 数值列的统计摘要(均值、中位数、最大值);
  • 前 3 行和后 3 行。

你大概会用到 df.shape、df.dtypes、df.describe()、df.head(3)、df.tail(3)——全是本节学过的方法。

点击查看参考答案
print("=== 规模 ===")
print(df.shape)

print("\n=== 类型 ===")
print(df.dtypes)

print("\n=== 数值摘要 ===")
print(df.describe())

print("\n=== 前 3 行 ===")
print(df.head(3))

print("\n=== 后 3 行 ===")
print(df.tail(3))

要点: \n 是换行符,用它把几段输出隔开,报告会好看很多。这是个很实用的小技巧。


练习小结#

题号练的是用到的核心方法
1从字典建表pd.DataFrame(字典)
2看行数列数df.shape、len(df)
3取列df["列"](Series)、df[["列1", "列2"]](DataFrame)
4看数据类型df.dtypes、df["列"].dtype
5预览数据df.head(n)、df.tail(n)

如果你这 5 题都能独立写出来,第 1 章的核心你已经掌握了。下一节是这一章的 10 个常见问题,把那些「看着眼熟但说不清区别」的地方一次性讲透。

阅读 --