3. Pandas基础:Series与DataFrame创建、索引与切片、数据读取
各位同学,欢迎来到第三章。说实话,Pandas 是我在金融数据处理中用得最多的库,没有之一。你想想看,每天面对几万行交易数据、几十个字段的财务报表,没有 Pandas 简直寸步难行。这一章,我就带你从零开始,把 Series 和 DataFrame 这两个核心数据结构彻底搞明白。
3.1 认识Pandas的两大核心:Series与DataFrame
Pandas 说白了就两个东西:Series 和 DataFrame。
- 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 提供了两套索引方式:loc 和 iloc。
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 创建数据结构、灵活地索引切片、从各种数据源读取数据。这三步是后续所有金融数据分析的基础。
好了,这一章就到这里。代码不多,但都是实打实的干货。你可以在自己的电脑上把每个例子都跑一遍,遇到问题很正常——我当年也是这么过来的。