# 4.7.1 时间序列生成与索引设置（问答库）

1. 【单选题·易】`pd.date_range()` 的作用是？
   A. 删除重复的日期记录
   B. 快速生成规则的时间序列
   C. 计算两个时间点之间的间隔
   D. 对时间序列数据重采样
   **答案：B**
   **解析：** 语料明确：`date_range()` 可以快速生成规则的时间序列，例如按天、按月、按年递增。计算间隔属于 4.7.2 的 `Timedelta`，重采样属于 4.7.3 的 `resample`。

2. 【单选题·易】课程中 `date_range()` 的 `freq` 参数取值 `D`、`M`、`Y` 分别表示？
   A. 小时、分钟、秒
   B. 天、月、年
   C. 日、周、季度
   D. 旬、月、年
   **答案：B**
   **解析：** 语料：`freq` 指定频率，`D`、`M`、`Y` 分别表示天、月、年。

3. 【判断题·易】时间序列数据是指按时间顺序排列的数据，数据框常以时间作为行标签保存时间序列数据。
   **答案：√**
   **解析：** 4.7 开篇定义：时间序列数据按时间顺序排列，通常用于金融市场、传感器、气象等；数据框常以时间作为行标签保存。

4. 【判断题·易】`date_range()` 生成的对象是可迭代对象，可通过索引访问其中的元素，元素是 `Timestamp` 对象。
   **答案：√**
   **解析：** 课程示例：`dates[0]` 得到 `Timestamp('2024-01-31 00:00:00', freq='M')`（对应按月生成时的第一个元素）。

5. 【多选题·中】关于 `pd.date_range()` 的常用参数，下列说法正确的有：
   A. `start` 指定起始日期
   B. `periods` 指定周期数
   C. `freq` 指定频率
   D. `axis=1` 表示按列生成时间序列
   **答案：ABC**
   **解析：** 课程给出三个参数：`start`、`periods`、`freq`。`date_range()` 没有用 `axis` 来生成日期序列，D 错误。

6. 【单选题·中】执行下列代码后，日期序列的第一个和最后一个元素分别是哪一天？

```python
import pandas as pd
dates = pd.date_range(start='2024-01-01', periods=10, freq='D')
print(dates[0])
print(dates[-1])
```

   A. `2024-01-01` 与 `2024-01-09`
   B. `2024-01-01` 与 `2024-01-10`
   C. `2024-01-01` 与 `2024-10-01`
   D. `2024-01-31` 与 `2024-10-31`
   **答案：B**
   **解析：** `freq='D'` 按天递增，`periods=10` 共 10 天，从 2024-01-01 到 2024-01-10。D 是 `freq='M'`（月末）的首尾日期。

7. 【单选题·中】执行下列代码后，`dates[0]` 对应的日期是？

```python
import pandas as pd
dates = pd.date_range(start='2024-01-01', periods=10, freq='ME')  # 课程写法：freq='M'
print(dates[0])
```

   A. `2024-01-01`（起始日当天）
   B. `2024-01-31`（对齐到月末）
   C. `2024-10-31`
   D. `2024-02-01`
   **答案：B**
   **解析：** 课程说明：`freq='M'` 生成按月序列，每个日期对齐到月末。从 2024-01-01 起第一个月末是 2024-01-31。较新版本 pandas 中 `M` 已改为 `ME`，结果相同。

8. 【多选题·中】要把时间设置为数据框的行标签，课程给出的做法包括：
   A. 字符串日期列先用 `pd.to_datetime()` 转换，再用 `set_index()` 设为索引
   B. 创建数据框时直接把 `pd.date_range()` 的结果作为 `index`
   C. 必须先对数据做 `resample()`，否则不能设时间索引
   D. 可用 `inplace=True` 让 `set_index()` 直接改原数据框
   **答案：ABD**
   **解析：** 语料给出两种路径：已有字符串日期列则 `to_datetime` + `set_index`；也可创建时传入 `date_range()`。`resample` 属于 4.7.3，不是设索引的前提。课程示例使用了 `inplace=True`。

9. 【判断题·中】执行 `df.set_index('日期')` 且不接收返回值、也不设 `inplace=True` 时，原数据框的行标签会立刻变成「日期」列。
   **答案：×**
   **解析：** `set_index()` 默认返回新数据框，不修改原对象。课程要改原对象时写 `df.set_index('日期', inplace=True)`，也可写成 `df = df.set_index('日期')`。

10. 【单选题·难】执行下列代码后，关于 `df.index` 的说法正确的是？

```python
import pandas as pd
from pandas import DataFrame
df = DataFrame({'日期': ['2024-8-1', '2024-8-2', '2024-8-3'],
                '数量': [81, 73, 62]})
df.set_index('日期', inplace=True)
print(type(df.index).__name__)
```

   A. 已是 `DatetimeIndex`，因为列名叫做「日期」
   B. 仍是普通 `Index`（字符串标签），因为没有先做 `to_datetime`
   C. 报错：字符串不能作为行标签
   D. 自动变成按月的 `PeriodIndex`
   **答案：B**
   **解析：** 列名不会让 pandas 自动识别为时间。字符串日期必须先 `pd.to_datetime()`，`set_index` 后才会得到 `DatetimeIndex`。未转换时只是普通标签索引，后续按时间切片、重采样会受影响。

11. 【简答题·中】请写出完整可运行代码：用 `date_range()` 生成从 2024-01-01 起共 10 天的日期序列，并取出第一个元素。再说明把 `freq` 改成按月时，第一个日期会变成什么、为什么。
    **答案：**

```python
import pandas as pd
dates = pd.date_range(start='2024-01-01', periods=10, freq='D')
print(dates[0])  # Timestamp('2024-01-01 00:00:00')
```

    按月时课程写法为 `freq='M'`（较新版本用 `freq='ME'`），第一个日期是 2024-01-31，因为按月频率对齐到月末，而不是保留起始日的“日”部分。
    **解析：** 评分要点：① 写出 `start`、`periods=10`、`freq='D'`；② 用索引取出 `dates[0]`；③ 说明按月对齐月末，首日为 2024-01-31。只写函数名不写参数，或把按月说成 2024-01-01，酌情扣分。

12. 【简答题·难】结合下列两种写法，回答：（1）第一种为什么要先 `to_datetime` 再 `set_index`？（2）`inplace=True` 起什么作用？（3）第二种写法与第一种在结果上有何相同点？

```python
import pandas as pd
from pandas import DataFrame

# 写法一：已有字符串日期列
date = ['2024-8-1', '2024-8-2', '2024-8-3', '2024-8-4', '2024-8-5',
        '2024-8-6', '2024-8-7', '2024-8-8', '2024-8-9', '2024-8-10']
num = [81, 73, 62, 50, 80, 99, 89, 54, 63, 78]
df1 = DataFrame({'日期': date, '数量': num})
df1['日期'] = pd.to_datetime(df1['日期'])
df1.set_index('日期', inplace=True)

# 写法二：创建时直接指定时间索引
dates = pd.date_range(start='2024-08-01', periods=10, freq='D')
df2 = pd.DataFrame(num, index=dates, columns=['数量'])
print(df1.head())
print(df2.head())
```

    **答案：**
    （1）「日期」列最初是字符串，不是时间类型。先 `to_datetime` 才能得到真正的时间数据，再 `set_index` 才会形成 `DatetimeIndex`，便于按时间查询、切片。
    （2）`inplace=True` 在原数据框上把「日期」设为行标签；若不设且不赋值，原对象仍是整数行标签。
    （3）两种写法都能得到以时间为行标签、以「数量」为列的数据框，索引从 2024-08-01 到 2024-08-10。写法一来自已有字符串列的转换，写法二由 `date_range()` 直接生成规则索引。
    **解析：** 评分要点：① 点明字符串必须转换，否则不是时间索引；② 说明 `set_index` 默认不改原对象；③ 指出两种途径都能把时间设为行标签，并对应课程的 8 月 1 日共 10 天示例。漏掉「未转换则不是 DatetimeIndex」或把两种写法说成必须同时使用，酌情扣分。
