Pandas: DataFrame 核心

最后更新:2026-08-26

DataFrame 是 Pandas 的核心数据结构——它是一张"带标签的二维表格",每一列是一个 Series,拥有独立的类型和名称。你可以把 DataFrame 想象成代码里的 Excel 表或 SQL 表,但它更强大:可编程、可扩展、可版本控制。本节带你深入理解 DataFrame 的本质结构。

⚠️ 注意: 以下代码需在本地 Python 环境中运行。

1. 你将学到


2. Charlie 的电商商品表

(1) 痛点:多列数据怎么一起管理

Charlie 经营一家电商网站,他需要管理商品数据:名称、类别、价格、库存、评分——5 列不同类型的数据。用 Series 的话,他需要维护 5 个独立的 Series 并确保它们的 Index 对齐。

PYTHON
import pandas as pd

# 5 separate Series — must keep index aligned manually
names = pd.Series(['Laptop', 'Phone', 'Tablet', 'Monitor', 'Keyboard'])
categories = pd.Series(['Electronics', 'Electronics', 'Electronics', 'Electronics', 'Accessories'])
prices = pd.Series([999.99, 699.99, 349.99, 449.99, 79.99])
stocks = pd.Series([50, 120, 80, 35, 200])
ratings = pd.Series([4.7, 4.5, 4.3, 4.6, 4.2])
# Which price goes with which product? Hope the index stays aligned!
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) 解法:DataFrame 把列绑在一起

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:DataFrame 管理商品数据(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'name': ['Laptop', 'Phone', 'Tablet', 'Monitor', 'Keyboard'],
    'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics', 'Accessories'],
    'price': [999.99, 699.99, 349.99, 449.99, 79.99],
    'stock': [50, 120, 80, 35, 200],
    'rating': [4.7, 4.5, 4.3, 4.6, 4.2]
})

print(df)
#        name     category    price  stock  rating
# 0    Laptop  Electronics   999.99     50     4.7
# 1     Phone  Electronics   699.99    120     4.5
# 2    Tablet  Electronics   349.99     80     4.3
# 3   Monitor  Electronics   449.99     35     4.6
# 4  Keyboard  Accessories    79.99    200     4.2

print(df['name'])     # a Series
print(df.loc[0])      # first row as a Series
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

5 列数据绑定在一个 DataFrame 中,列名自描述,行自动对齐。

(3) 收益:DataFrame 是"列的集合"

DataFrame 不是"二维 ndarray",而是"Series 的有序字典"——每一列是独立的 Series,有自己的类型,但共享同一个行 Index。


3. DataFrame 的本质结构

(1) 内部结构图解

100%
graph TB
    subgraph DataFrame
        direction TB
        COL["Columns Index<br/>(name, category, price, stock, rating)"]
        ROW["Row Index<br/>(0, 1, 2, 3, 4)"]
        S1["Series: name<br/>dtype: object"]
        S2["Series: category<br/>dtype: object"]
        S3["Series: price<br/>dtype: float64"]
        S4["Series: stock<br/>dtype: int64"]
        S5["Series: rating<br/>dtype: float64"]
    end
    ROW --> S1
    ROW --> S2
    ROW --> S3
    ROW --> S4
    ROW --> S5
    COL --> S1
    COL --> S2
    COL --> S3
    COL --> S4
    COL --> S5
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。
概念 说明 类比
行 Index 所有列共享的行标签 Excel 行号
列 Columns 每列的名称标签 Excel 列头
列 Series 每列独立的 Series Excel 单列
values 底层 2D ndarray 原始数据矩阵

(2) DataFrame vs ndarray 2D

特性 NumPy 2D ndarray Pandas DataFrame
类型约束 全局同一 dtype 每列独立 dtype
行标签 无(整数位置) Index(可自定义)
列标签 无(整数位置) Columns(列名)
列选取 arr[:, 2] df['price']
行选取 arr[0, :] df.loc[0]
混合类型 不支持 原生支持
缺失值 np.nan(仅浮点) NaN / NaT / pd.NA
📌 重点: DataFrame 的 values 属性返回 2D ndarray,但当你有混合类型时它会变成 object 类型——性能会大幅下降。需要纯数值运算时,先选取数值列再做 .values


4. 创建 DataFrame 的多种方式

(1) 从字典创建(最常用)

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:字典创建 DataFrame(难度⭐)

PYTHON
import pandas as pd

# Dict of lists: keys = column names, values = column data
df = pd.DataFrame({
    'product': ['Coffee', 'Tea', 'Juice', 'Water'],
    'price': [4.50, 3.80, 5.20, 1.50],
    'calories': [5, 2, 120, 0]
})
print(df)
#   product  price  calories
# 0  Coffee   4.50         5
# 1     Tea   3.80         2
# 2    Juice   5.20       120
# 3    Water   1.50         0

# Custom row index
df2 = pd.DataFrame({
    'product': ['Coffee', 'Tea', 'Juice'],
    'price': [4.50, 3.80, 5.20]
}, index=['A001', 'A002', 'A003'])
print(df2.index)  # Index(['A001', 'A002', 'A003'])
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) 从列表的列表创建

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:列表的列表创建 DataFrame(难度⭐)

PYTHON
import pandas as pd

# List of lists: each inner list = one row
data = [
    ['Coffee', 4.50, 5],
    ['Tea', 3.80, 2],
    ['Juice', 5.20, 120],
    ['Water', 1.50, 0]
]
df = pd.DataFrame(data, columns=['product', 'price', 'calories'])
print(df)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(3) 从字典列表创建

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:字典列表创建 DataFrame(难度⭐)

PYTHON
import pandas as pd

# List of dicts: each dict = one row
data = [
    {'product': 'Coffee', 'price': 4.50, 'calories': 5},
    {'product': 'Tea', 'price': 3.80, 'calories': 2},
    {'product': 'Juice', 'price': 5.20, 'calories': 120}
]
df = pd.DataFrame(data)
print(df)
# Missing keys become NaN
data2 = [
    {'product': 'Coffee', 'price': 4.50},
    {'product': 'Tea', 'calories': 2}
]
df2 = pd.DataFrame(data2)
print(df2)
#   product  price  calories
# 0  Coffee   4.50       NaN
# 1     Tea    NaN       2.0
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(4) 从 NumPy ndarray 创建

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:从 ndarray 创建 DataFrame(难度⭐)

PYTHON
import numpy as np
import pandas as pd

arr = np.random.randn(4, 3)  # 4 rows, 3 columns of random numbers
df = pd.DataFrame(arr, columns=['A', 'B', 'C'])
print(df.shape)   # (4, 3)
print(df.dtypes)  # all float64
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(5) 创建方式对比

方式 语法 特点 适用场景
字典 pd.DataFrame({'col': [data]}) 列优先,最自然 最常用
列表列表 pd.DataFrame([[r1c1, ...], ...]) 行优先 逐行构建
字典列表 pd.DataFrame([{'col': val, ...}, ...]) 行优先,缺失自动NaN API/JSON数据
ndarray pd.DataFrame(np.array(...)) 同质数据 NumPy数据转换
read_csv pd.read_csv('file.csv') 从文件加载 实际项目最常用

5. 查看与探查数据

(1) 快速查看:head / tail / sample

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:查看 DataFrame(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'name': ['Laptop', 'Phone', 'Tablet', 'Monitor', 'Keyboard',
             'Mouse', 'Headset', 'Speaker', 'Camera', 'Charger'],
    'price': [999.99, 699.99, 349.99, 449.99, 79.99,
              29.99, 149.99, 89.99, 599.99, 19.99],
    'stock': [50, 120, 80, 35, 200, 300, 150, 180, 25, 500]
})

print(df.head())      # first 5 rows
print(df.head(3))     # first 3 rows
print(df.tail(2))     # last 2 rows
print(df.sample(3))   # random 3 rows (for inspection)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) 数据概览:info

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:info 方法详解(难度⭐⭐)

PYTHON
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'Carol', 'David'],
    'age': [28, 34, 25, 30, 45],
    'salary': [75000.0, 92000.0, np.nan, 88000.0, 105000.0],
    'department': ['Sales', 'Engineering', 'Marketing', 'Sales', 'Management']
})

df.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 5 entries, 0 to 4
# Data columns (total 4 columns):
#  #   Column      Non-Null Count  Dtype
# ---  ------      --------------  -----
#  0   name        5 non-null      object
#  1   age         5 non-null      int64
#  2   salary      4 non-null      float64  ← 1 missing value!
#  3   department  5 non-null      object
# dtypes: float64(1), int64(1), object(2)
# memory usage: 288.0+ bytes
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

info() 是数据分析的第一步——它告诉你:有多少行、每列的类型、是否有缺失值、内存占用。

(3) 统计摘要:describe

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:describe 统计摘要(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'price': [999.99, 699.99, 349.99, 449.99, 79.99],
    'stock': [50, 120, 80, 35, 200],
    'rating': [4.7, 4.5, 4.3, 4.6, 4.2]
})

# Numeric columns only (default)
print(df.describe())
#           price    stock   rating
# count     5.00     5.00     5.00
# mean    515.79    97.00     4.46
# std     347.31    69.72     0.21
# min      79.99    35.00     4.20
# 25%     349.99    50.00     4.30
# 50%     449.99    80.00     4.50
# 75%     699.99   120.00     4.60
# max     999.99   200.00     4.70

# Include all columns
print(df.describe(include='all'))
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。
方法 显示内容 适用场景
df.head() 前 5 行 快速查看数据格式
df.info() 行数/列类型/缺失值/内存 第一步必看
df.describe() 数值列统计摘要 了解分布
df.shape (行数, 列数) 数据规模
df.dtypes 每列类型 类型检查

6. DataFrame 核心属性

(1) 属性速查表

属性 返回类型 说明 示例
df.shape tuple (行数, 列数) (5, 4)
df.index Index 行标签 RangeIndex(0, 5)
df.columns Index 列名 Index(['name', 'age', ...])
df.dtypes Series 每列类型 name: object, age: int64
df.values ndarray 底层数据 2D array
df.ndim int 维度数 2
df.size int 元素总数 20 (5行4列)
df.T DataFrame 转置 行列互换

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:核心属性一览(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [28, 34, 25],
    'salary': [75000.0, 92000.0, 68000.0]
})

print(f"Shape:    {df.shape}")      # (3, 3)
print(f"Index:    {df.index}")      # RangeIndex(0, 3)
print(f"Columns:  {df.columns}")    # Index(['name', 'age', 'salary'])
print(f"Dtypes:\n{df.dtypes}")
print(f"Size:     {df.size}")       # 9
print(f"Ndim:     {df.ndim}")       # 2
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) 列选取与添加

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:列操作(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [28, 34, 25],
    'salary': [75000.0, 92000.0, 68000.0]
})

# Select single column → Series
print(type(df['name']))   # <class 'pandas.core.series.Series'>

# Select multiple columns → DataFrame
print(df[['name', 'salary']])

# Add new column
df['bonus'] = df['salary'] * 0.1
df['level'] = df['age'].apply(lambda x: 'Senior' if x >= 30 else 'Junior')
print(df)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(3) 转置

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:DataFrame 转置(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'Q1': [320, 280, 350],
    'Q2': [410, 390, 420]
}, index=['Product A', 'Product B', 'Product C'])

print(df.T)
#              Product A  Product B  Product C
# Q1          320        280        350
# Q2          410        390        420
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

7. 完整示例:电商商品表全流程

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:商品数据创建与探查(难度⭐⭐⭐)

PYTHON
import pandas as pd
import numpy as np

# ============================================
# Comprehensive example: E-commerce product
# table creation and exploration
# ============================================

# 1. Create DataFrame
products = pd.DataFrame({
    'name': ['Laptop', 'Phone', 'Tablet', 'Monitor', 'Keyboard',
             'Mouse', 'Headset', 'Speaker'],
    'category': ['Electronics', 'Electronics', 'Electronics',
                 'Electronics', 'Accessories', 'Accessories',
                 'Accessories', 'Accessories'],
    'price': [999.99, 699.99, 349.99, 449.99, 79.99,
              29.99, 149.99, 89.99],
    'stock': [50, 120, 80, 35, 200, 300, 150, 180],
    'rating': [4.7, 4.5, 4.3, 4.6, 4.2, 4.0, 4.4, 4.1]
})

# 2. Overview
print("=== Product Catalog Overview ===")
print(f"Products: {len(products)}")
print(f"Categories: {products['category'].unique().tolist()}")
print(f"Columns: {products.columns.tolist()}")

# 3. Data types and memory
print(f"\n=== Data Types ===")
print(products.dtypes)
print(f"\nMemory usage: {products.memory_usage(deep=True).sum() / 1024:.1f} KB")

# 4. Quick statistics
print(f"\n=== Price Statistics ===")
print(products['price'].describe())

# 5. Inventory value per product
products['inventory_value'] = products['price'] * products['stock']
print(f"\n=== Top 3 by Inventory Value ===")
print(products.nlargest(3, 'inventory_value')[['name', 'inventory_value']])

# 6. Category breakdown
print(f"\n=== Category Summary ===")
cat_summary = products.groupby('category').agg(
    count=('name', 'count'),
    avg_price=('price', 'mean'),
    total_stock=('stock', 'sum')
)
print(cat_summary)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

预期输出(节选):

TEXT 📖 仅展示
=== Product Catalog Overview ===
Products: 8
Categories: ['Electronics', 'Accessories']
Columns: ['name', 'category', 'price', 'stock', 'rating']

=== Price Statistics ===
count       8.00
mean      349.99
std       339.32
min        29.99
max       999.99

=== Top 3 by Inventory Value ===
      name  inventory_value
0   Laptop         49999.50
1    Phone         83998.80
3  Monitor         15749.65

=== Category Summary ===
              count  avg_price  total_stock
category
Accessories       4      87.24          830
Electronics       4     624.99          285

❓ 常见问题

Q DataFrame 和 Series 什么关系?
A DataFrame 是 Series 的有序集合——每一列是一个 Series,所有列共享同一个行 Index。取单列返回 Series,取多列返回 DataFrame。取单行也返回 Series(列名作为 Index)。
Q 列能用数字索引吗?
A 可以。如果列名是整数(如 0, 1, 2),用 df[0] 访问会歧义——Pandas 把它当列名而非位置。此时必须用 df.iloc[:, 0] 按位置访问或 df.loc[:, 0] 按标签访问。建议列名用字符串避免混淆。
Q info 和 describe 区别?
A info 显示结构信息(行数/列类型/缺失值/内存),describe 显示统计摘要(均值/标准差/分位数/极值)。info 是"数据长什么样",describe 是"数值分布如何"。两者互补,首次接触数据时都应查看。
Q 如何添加/删除列?
A 添加列用 df['new_col'] = values(添加到末尾)或 df.insert(pos, 'new_col', values)(指定位置)。删除列用 df.drop('col', axis=1)del df['col']。drop 返回新 DataFrame(不修改原数据),del 直接修改。
Q values 返回什么?
A df.values 返回底层 2D NumPy ndarray。如果 DataFrame 有混合类型(如 object + int64),ndarray 的 dtype 会升级为 object,丧失向量化性能。纯数值 DataFrame 的 values 保持数值 dtype。
Q DataFrame 如何转置?
Adf.Tdf.transpose()。转置后行变列、列变行。注意:转置后如果原 DataFrame 有混合类型,所有列会变为 object 类型(因为 ndarray 要求同质)。
Q 创建 DataFrame 用字典还是列表?
A 字典最自然(键=列名,值=列数据),推荐日常使用。字典列表适合逐行构建(如从 API 获取 JSON 数据)。ndarray 适合纯数值数据。实际项目中 80% 的情况用 pd.read_csv() 从文件加载。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 3 种方式创建学生表(name / math / english / science),打印 info 和 describe 结果。
  2. 进阶题(难度⭐⭐):创建一个含缺失值的员工表(name / age / salary / department,其中 salary 有 2 个 NaN),完成:info 检查缺失值 → 计算每列非空比例 → 添加一列 salary_level(salary>80000 为 High 否则 Low,NaN 为 Unknown)。
  3. 挑战题(难度⭐⭐⭐):从字典列表构建 DataFrame(5 条记录,部分键缺失),完成:检查缺失 → 用每列均值/众数填充 → 计算每行的非空字段数 → 添加一列 completeness(非空比例),最终输出完整的 describe 报告。

← 上一课:Series 入门 · 下一课:Index 索引 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏