3. Pandas基础:Series与DataFrame创建、索引与切片、数据读取

各位同学,欢迎来到第三章。说实话,Pandas 是我在金融数据处理中用得最多的库,没有之一。你想想看,每天面对几万行交易数据、几十个字段的财务报表,没有 Pandas 简直寸步难行。这一章,我就带你从零开始,把 Series 和 DataFrame 这两个核心数据结构彻底搞明白。

3.1 认识Pandas的两大核心:Series与DataFrame

Pandas 说白了就两个东西:SeriesDataFrame

  • Series:一维的标签数组。你可以把它想象成 Excel 里的一列数据,每个值都有一个索引标签。
  • DataFrame:二维的表格数据结构。有行有列,每列可以是不同的类型(数值、字符串、日期等)。这就是我们处理金融数据的主力。

我个人习惯把 DataFrame 看作「多个 Series 拼在一起」。每一列其实就是一个 Series,它们共享同一个行索引。这个理解方式,在后续做数据合并时会特别有用。

核心记忆点:Series = 带标签的一列数据;DataFrame = 多个Series组成的表格。

3.2 创建Series与DataFrame

3.2.1 创建Series

创建 Series 最简单的方式,就是传一个列表进去:

import pandas as pd

# 从列表创建
s1 = pd.Series([100, 200, 300, 400])
print(s1)
# 输出:
# 0    100
# 1    200
# 2    300
# 3    400
# dtype: int64

嗯,这里要注意:默认索引是从 0 开始的整数。但在金融场景里,我们经常要用日期或股票代码做索引。比如:

# 指定索引
s2 = pd.Series([28.5, 30.2, 29.8], 
               index=['2024-01-01', '2024-01-02', '2024-01-03'])
print(s2)
# 输出:
# 2024-01-01    28.5
# 2024-01-02    30.2
# 2024-01-03    29.8
# dtype: float64

我在项目中遇到过一个问题:用日期做索引时,如果不指定 dtype,Pandas 默认会把日期字符串当成普通字符串。所以后来我习惯在创建时就指定:dtype='float64',避免后续计算时报类型错误。

3.2.2 创建DataFrame

创建 DataFrame 的方法有好几种,我最常用的是传一个字典进去:

# 从字典创建DataFrame
data = {
    '股票代码': ['000001', '600519', '000002'],
    '收盘价': [32.5, 1850.0, 14.8],
    '成交量': [1200000, 350000, 890000]
}
df = pd.DataFrame(data)
print(df)
# 输出:
#   股票代码     收盘价      成交量
# 0  000001    32.5  1200000
# 1  600519  1850.0   350000
# 2  000002    14.8   890000

字典的键就是列名,值就是列数据。这个方式最直观,也最接近我们平时看表格的习惯。

还有一种方式是从嵌套列表创建,适合从 API 接口拿到的原始数据:

# 从嵌套列表创建
rows = [
    ['000001', 32.5, 1200000],
    ['600519', 1850.0, 350000],
    ['000002', 14.8, 890000]
]
df2 = pd.DataFrame(rows, columns=['股票代码', '收盘价', '成交量'])

小技巧:如果你不确定数据长什么样,先创建一个只有几行的小 DataFrame 试试看。我经常在 Jupyter Notebook 里这样调试,比直接读大文件快得多。

3.3 索引与切片:数据定位的核心技能

做金融分析,80% 的时间都在做一件事:找到你想要的数据。Pandas 提供了两套索引方式:lociloc

3.3.1 使用loc进行标签索引

loc 是基于标签(行名、列名)的索引方式。说白了,你用「名字」来找数据:

# 假设我们有一个带日期索引的DataFrame
dates = pd.date_range('2024-01-01', periods=5, freq='D')
df_daily = pd.DataFrame({
    '开盘价': [30, 31, 29, 32, 33],
    '收盘价': [31, 30, 31, 33, 32]
}, index=dates)

# 取某一天的数据
print(df_daily.loc['2024-01-03'])
# 输出:
# 开盘价    29
# 收盘价    31
# Name: 2024-01-03 00:00:00, dtype: int64

# 取某几行某几列
print(df_daily.loc['2024-01-02':'2024-01-04', '开盘价'])
# 输出:
# 2024-01-02    31
# 2024-01-03    29
# 2024-01-04    32
# Name: 开盘价, dtype: int64

注意看,loc 的切片是包含终点的。这和 Python 原生的切片不一样,我刚开始用的时候经常搞混。

3.3.2 使用iloc进行位置索引

iloc 是基于整数位置的索引。你按「第几行、第几列」来找:

# 取第一行数据
print(df_daily.iloc[0])
# 输出:
# 开盘价    30
# 收盘价    31
# Name: 2024-01-01 00:00:00, dtype: int64

# 取前3行,第1列
print(df_daily.iloc[:3, 0])
# 输出:
# 2024-01-01    30
# 2024-01-02    31
# 2024-01-03    29
# Name: 开盘价, dtype: int64

iloc 的切片是左闭右开的,和 Python 列表一致。这一点要记牢。

避坑指南:我曾经在写策略回测时,用 iloc 取了最后一行数据,结果因为索引越界导致整个回测崩溃。后来我养成了一个习惯:取数据前先用 shape 看一眼行数列数。

3.4 数据读取:从CSV/Excel/数据库加载数据

实际工作中,数据很少是手动创建的。大部分时候,我们要从文件或数据库里读数据。Pandas 的读取函数设计得很人性化,参数名基本一看就懂。

3.4.1 读取CSV文件

CSV 是金融数据最常见的格式。交易所、数据供应商给的日线数据,基本都是 CSV:

# 读取CSV文件
df_csv = pd.read_csv('stock_data.csv')

# 常用参数
df_csv = pd.read_csv(
    'stock_data.csv',
    encoding='utf-8',        # 处理中文乱码
    parse_dates=['日期'],     # 自动解析日期列
    index_col='日期',         # 指定日期列为索引
    dtype={'成交量': 'int64'} # 指定列的数据类型
)

嗯,这里有个坑:很多金融 CSV 文件是 GBK 编码的,尤其是国内数据源。如果你读出来全是乱码,试试 encoding='gbk'encoding='gb2312'

3.4.2 读取Excel文件

Excel 在金融行业也很常见,特别是财务报表、研报数据:

# 读取Excel文件
df_excel = pd.read_excel('financial_report.xlsx', sheet_name='利润表')

# 读取多个sheet
sheets = pd.read_excel('financial_report.xlsx', sheet_name=None)
# 返回一个字典,键是sheet名,值是DataFrame

我个人习惯用 sheet_name=None 一次读完所有 sheet,然后按名字取。这样不用反复打开文件,效率高很多。

3.4.3 从数据库读取

当数据量大了以后(比如几百万条 tick 数据),CSV 和 Excel 就扛不住了。这时候要用数据库。Pandas 配合 SQLAlchemy 可以直连各种数据库:

from sqlalchemy import create_engine

# 连接MySQL数据库
engine = create_engine('mysql+pymysql://用户名:密码@主机地址:端口/数据库名')

# 执行SQL查询,结果直接变成DataFrame
df_sql = pd.read_sql_query(
    "SELECT trade_date, close FROM stock_daily WHERE code='000001'",
    engine
)

# 或者直接读取整张表
df_table = pd.read_sql_table('stock_daily', engine)

我在做量化系统时,每天开盘前都要从数据库拉取全市场数据。用 read_sql_query 配合参数化查询,既安全又高效。记住:永远不要用字符串拼接 SQL,会有 SQL 注入风险。

效率建议:读大文件时,加一个 nrows=1000 参数先看看数据长什么样。确认没问题了,再去掉限制读全量。这招帮我省了不少调试时间。

3.5 本章知识体系总览

下面这张图,是我自己梳理的本章知识结构。你可以把它当成一个「思维导图」,学完一章回来看看,能帮你把零散的知识点串起来。

Pandas基础 Series • 一维标签数组 • 从列表/字典创建 • 自定义索引 DataFrame • 二维表格结构 • 从字典/列表创建 • 列名与行索引 索引与切片 • loc:基于标签索引 • iloc:基于位置索引 • 切片规则区别 数据读取 • read_csv() • read_excel() • read_sql_query() 读取常用参数 • encoding:编码处理 • parse_dates:日期解析 • index_col:索引列 • dtype:类型指定 核心:创建 → 索引 → 读取,三步搞定金融数据

这张图把本章的核心内容都串起来了。你学完这一章,应该能做到:用 Pandas 创建数据结构、灵活地索引切片、从各种数据源读取数据。这三步是后续所有金融数据分析的基础。

好了,这一章就到这里。代码不多,但都是实打实的干货。你可以在自己的电脑上把每个例子都跑一遍,遇到问题很正常——我当年也是这么过来的。


专注资料整理