pandas 数据结构深度解析:从 Series 到 DataFrame 的底层逻辑与实践

在数据分析的日常工作中,我们经常需要处理各种形态的数据 —— 从一维的用户评分序列到二维的交易明细表,选择合适的数据结构往往是高效处理的第一步。pandas 的 Series 和 DataFrame 作为核心数据结构,以其标签化特性和高效的底层实现,成为数据科学家的 “瑞士军刀”。本文将结合完整的数据示例与输出展示,深入解析两者的底层逻辑,让你直观理解每个操作的效果。

一、Series 基础:带标签的动态一维数组

1. 多形态创建:灵活适配数据输入

Series 可以看作是 NumPy 数组的 “增强版”,最大的特点是引入了索引标签,让数据与标签一一绑定。以下是带输出的完整示例

▍从列表 / 数组创建(自动生成 RangeIndex)

python

import pandas as pd
import numpy as np

# 创建带缺失值的Series
s_list = pd.Series([1, 3, 5, np.nan, 6, 8])
print("列表创建Series:")
print(s_list)

输出结果

plaintext

0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64

关键点:索引为 0-based 整数,缺失值np.nan会被自动识别,后续计算默认排除缺失值。

▍从字典创建(键为索引,值为数据)

python

d = {"a": 0.0, "b": 1.0, "c": 2.0}
s_dict = pd.Series(d)
print("\n字典创建Series:")
print(s_dict)

输出结果

plaintext

a    0.0
b    1.0
c    2.0
dtype: float64

注意:若索引与字典键不匹配(如指定index=["a", "b", "d"]),缺失值会自动填充为NaN

▍从标量值创建(指定索引重复填充)

python

s_scalar = pd.Series(5.0, index=["a", "b", "c"])
print("\n标量值创建Series:")
print(s_scalar)

输出结果

plaintext

a    5.0
b    5.0
c    5.0
dtype: float64

2. 类数组与类字典特性:无缝切换操作习惯

▍类 ndarray 特性:向量化操作与切片

python

# 向量化运算:对Series应用指数函数
s_vectorized = np.exp(s_list)
print("\n向量化运算结果:")
print(s_vectorized)

输出结果

plaintext

0     2.718282
1    20.085537
2    148.413159
3         NaN
4    403.428793
5   2980.957987
dtype: float64
▍类 dict 特性:标签访问与安全获取

python

# 标签访问
print("\ns_dict['b']的值:", s_dict["b"])  # 输出:1.0

# 安全获取缺失标签
print("\n安全获取f的值:", s_dict.get("f", np.nan))  # 输出:nan(默认返回NaN)

3. 数据类型与底层存储

▍分类数据类型(节省内存)

python

s_category = pd.Series(["test", "train", "test"], dtype="category")
print("\n分类类型Series:")
print(s_category)
print("数据类型:", s_category.dtype)

输出结果

plaintext

0     test
1    train
2     test
dtype: category
Categories (2, object): ['test', 'train']
▍底层数组访问

python

# 获取ExtensionArray
print("\n底层数组:", s_category.array)
# 转换为NumPy数组
print("转换为NumPy数组:", s_category.to_numpy())

输出结果

plaintext

底层数组: <CategoricalArray with categories ['test', 'train']>
转换为NumPy数组: ['test' 'train' 'test']

二、DataFrame 核心:二维结构化数据的终极方案

1. 多元化构建:适配复杂数据场景

▍字典嵌套 Series(自动对齐索引)

python

d = {
    "A": pd.Series([1, 2, 3], index=["a", "b", "c"]),
    "B": pd.Series([4, 5], index=["b", "c"])  # 索引对齐,a行B列为NaN
}
df_dict_series = pd.DataFrame(d)
print("\n字典嵌套Series创建DataFrame:")
print(df_dict_series)

输出结果

plaintext

   A    B
a  1  NaN
b  2  4.0
c  3  5.0
▍结构化数组(字段映射为列)

python

data = np.zeros(2, dtype=[("A", int), ("B", float)])
data[:] = [(1, 2.0), (2, 3.0)]
df_struct = pd.DataFrame(data)
print("\n结构化数组创建DataFrame:")
print(df_struct)

输出结果

plaintext

   A    B
0  1  2.0
1  2  3.0

2. 行列操作:索引对齐的魔法

▍列访问与索引对齐

python

# 列访问示例
print("\n访问'A'列:")
print(df_dict_series["A"])

输出结果

plaintext

a    1.0
b    2.0
c    3.0
Name: A, dtype: float64
▍索引对齐运算

python

df1 = pd.DataFrame({"A": [1, 2], "B": [3, 4]}, index=["x", "y"])
df2 = pd.DataFrame({"A": [5, 6], "B": [7, 8]}, index=["y", "z"])
result = df1 + df2  # 自动对齐索引x/y/z
print("\n索引对齐运算结果:")
print(result)

输出结果

plaintext

     A    B
x  NaN  NaN
y  7.0  11.0
z  NaN  NaN

3. 动态修改:高效调整数据结构

▍列添加与类型转换

python

# 新增列
df_dict_series["C"] = df_dict_series["A"] * 2
print("\n新增列后:")
print(df_dict_series)

# 转换类型
df_dict_series["A"] = df_dict_series["A"].astype("int32")
print("\n转换A列为int32后:")
print(df_dict_series.dtypes)

输出结果

plaintext

新增列后:
   A    B   C
a  1  NaN   2
b  2  4.0   4
c  3  5.0   6

转换A列为int32后:
A     int32
B    float64
C     int64
dtype: object

三、索引与数据访问:精准操作的核心逻辑

1. 标签索引.loc[]:基于语义的精准定位

python

# 创建带日期索引的DataFrame
dates = pd.date_range("2023-01-01", periods=3, names="日期")
df_date = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=dates)
print("\n标签索引示例:")
print(df_date.loc["2023-01-01":"2023-01-02", ["A", "B"]])

输出结果

plaintext

            A  B
日期           
2023-01-01  1  4
2023-01-02  2  5

2. 位置索引.iloc[]:基于整数的机械定位

python

print("\n位置索引示例:")
print(df_date.iloc[0:2, 0])  # 前2行,第1列

输出结果

plaintext

2023-01-01    1
2023-01-02    2
Name: A, dtype: int64

3. 布尔索引:动态过滤数据

python

# 筛选A列大于1的行
print("\n布尔索引示例:")
print(df_date[df_date["A"] > 1])

输出结果

plaintext

            A  B
日期           
2023-01-02  2  5
2023-01-03  3  6

四、数据操作与生态集成

1. 向量化运算:性能提升的核心

python

# 标量广播运算
df_scalar = df_date * 2
print("\n向量化运算(乘以2):")
print(df_scalar)

输出结果

plaintext

            A   B
日期           
2023-01-01  2   8
2023-01-02  4  10
2023-01-03  6  12

2. 缺失值处理:数据清洗的必修课

python

df_missing = df_date.copy()
df_missing.loc["2023-01-01", "B"] = np.nan  # 人为添加缺失值
print("\n含缺失值的DataFrame:")
print(df_missing)

# 填充缺失值
df_filled = df_missing.fillna(0)
print("\n填充后:")
print(df_filled)

输出结果

plaintext

含缺失值的DataFrame:
            A    B
日期           
2023-01-01  1  NaN
2023-01-02  2  5.0
2023-01-03  3  6.0

填充后:
            A    B
日期           
2023-01-01  1  0.0
2023-01-02  2  5.0
2023-01-03  3  6.0

五、高级特性与最佳实践

1. 分组与聚合:复杂统计的利器

python

# 示例数据
df_group = pd.DataFrame({
    "类别": ["A", "A", "B", "B"],
    "数值": [1, 2, 3, 4]
})
print("\n分组聚合示例:")
print(df_group.groupby("类别")["数值"].sum())

输出结果

plaintext

类别
A    3
B    7
Name: 数值, dtype: int64

2. 数据合并与重塑:多表联动处理

▍纵向合并(concat)

python

df1 = pd.DataFrame({"A": [1, 2], "B": [3, 4]}, index=[1, 2])
df2 = pd.DataFrame({"A": [5, 6], "B": [7, 8]}, index=[3, 4])
result_concat = pd.concat([df1, df2])
print("\n纵向合并结果:")
print(result_concat)

输出结果

plaintext

   A  B
1  1  3
2  2  4
3  5  7
4  6  8
▍透视表(pivot_table)

python

df_pivot = pd.DataFrame({
    "日期": ["2023-01-01", "2023-01-01", "2023-01-02", "2023-01-02"],
    "产品": ["苹果", "香蕉", "苹果", "香蕉"],
    "销量": [10, 20, 15, 25]
})
print("\n透视表结果:")
print(pd.pivot_table(df_pivot, values="销量", index="日期", columns="产品"))

输出结果

plaintext

产品   香蕉  苹果
日期           
2023-01-01  20.0  10.0
2023-01-02  25.0  15.0

总结

通过以上带输出的完整示例,我们深入解析了 Series 和 DataFrame 的核心操作。关键点包括:

  1. 标签化数据模型:索引对齐是 pandas 的灵魂,确保不同数据源可直接运算;
  2. 向量化优先:任何情况下优先使用向量化操作(如df * 2),避免循环;
  3. 数据类型优化:合理使用分类类型(category)、数值类型(int32)减少内存占用;
  4. 索引精准访问.loc[].iloc[]需严格区分,避免混淆导致的错误。

建议在实际项目中,每次创建数据结构后,用print()head()查看数据形态,确保索引和数据类型符合预期。后续将分享更多关于时间序列分析、性能调优的实战技巧,欢迎关注!

如果觉得本文对你有帮助,欢迎点赞、收藏,你的支持是我持续输出技术干货的动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佑瞻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值