在Python数据分析的生态系统中,Pandas无疑是核心工具之一。如果你已经熟悉了Series一维数据结构,那么今天我们将迈入Pandas的另一核心——DataFrame。与TypeScript中的对象、Go中的结构体、C++中的类类似,DataFrame是Python中组织二维数据的标准方式。本文将带你从零掌握DataFrame的创建与结构,为后续的数据清洗、转换和可视化打下坚实基础。

一、DataFrame介绍与结构

DataFrame可以看作是多个Series的组合,它是一种二维的数据结构,每一行被称为“记录”,每一列也有自身的“名称”。通过“列名”与“索引”,我们可以精准定位到某一个具体的数值。这种设计类似于JavaScript中的二维数组,但功能更为强大。

核心概念:DataFrame本质上是一个带有标签的二维数组,行和列都有索引。你可以把它想象成一张Excel表格或SQL数据库表。每一列可以是不同的数据类型(整数、浮点数、字符串等),这比Go中的切片或C++中的数组更灵活。

⚠️ 注意:DataFrame的行索引默认为从0开始的整数,但你可以自定义为字符串、日期等类型,这在时间序列分析中尤为常见。列索引则通常用字符串表示,方便语义化访问。

二、DataFrame的创建方法

1. 引入Pandas库

在开始任何Pandas操作之前,首先需要导入库。通常我们使用import pandas as pd的惯例,就像在TypeScript中导入模块一样。这是所有Pandas代码的起点。

import pandas as pd
import numpy as np

2. 通过Series创建DataFrame

如果你已经熟悉了Series,那么将多个Series组合成一个DataFrame是非常直观的。每个Series会成为DataFrame的一列,而Series的索引会自动对齐成为DataFrame的行索引。这种方法在数据科学项目中常用于将多个一维数据源整合为二维结构。

实战场景:假设你从多个API接口获取了不同维度的数据(如温度、湿度、风速),每个维度都是一个Series,通过pd.DataFrame()可以快速合并为一张表格,方便后续分析。

s_1 = pd.Series((np.random.randint(1, 120) for _ in range(15)))
s_2 = pd.Series((np.random.randint(1, 200) for _ in range(15)))
print(s_1, "\n")
print(s_2, "\n")
df_1 = pd.DataFrame({"第1列":s_1, "第2列":s_2})
print(df_1, "\n")
print(type(df_1))
print(type(df_1["第1列"]))
print(type(df_1["第2列"]))

运行上述代码,你将看到如下输出,每一列对应一个Series,行索引自动对齐:

0     75
1      7
2     44
3     30
4     77
5     23
6     10
7     78
8     83
9     74
10     2
11    40
12    76
13    86
14    46
dtype: int64
0      47
1      89
2     191
3      80
4      12
5     106
6     199
7     172
8      62
9     115
10     83
11     38
12    182
13     94
14    128
dtype: int64
    第1列  第2列
0    75   47
1     7   89
2    44  191
3    30   80
4    77   12
5    23  106
6    10  199
7    78  172
8    83   62
9    74  115
10    2   83
11   40   38
12   76  182
13   86   94
14   46  128


最佳实践:在创建时,可以指定index参数来覆盖默认索引,或者使用columns参数来重命名列。这在数据清洗阶段非常实用。

3. 通过“字典”创建DataFrame

这是最常用的创建方式之一。字典的将成为列名,(列表或数组)将成为列数据。这种方式与JavaScript中的对象字面量类似,非常符合直觉。在Go或C++中,你可能需要定义结构体并逐行填充,而Python的字典方式则更加简洁。

原理说明:Pandas会自动根据字典值的长度推断行数,并生成默认的行索引。如果各个列表长度不一致,Pandas会抛出错误,因此需要确保数据对齐。

df_2 = pd.DataFrame({
    "Number":[f"00{num}" if len(str(num)) == 1 else f"0{num}" for num in range(1, 16)],
    "Name":["Emma", "Liam", "Chloe", "Felix", "Lila", "Leo", "Mia",  "Freya", "Arlo", "Elora", "Finn", "Wren", "Olivia", "Noah", "Ava"],
    "Result":[(f"{np.random.uniform(1, 100):.2f}") for i in range(15)]
})
print(df_2, "\n")
print(type(df_2))
print(type(df_2["Number"]))
print(type(df_2["Name"]))
print(type(df_2["Result"]))

执行后,你会看到结构清晰的表格,每一列都有明确的标签:

   Number    Name Result
0     001    Emma  13.62
1     002    Liam  97.02
2     003   Chloe  21.14
3     004   Felix

⚠️ 常见问题:如果字典中的值是Series而不是列表,Pandas会尝试对齐索引。如果索引不匹配,缺失值会用NaN填充。这在合并不同来源的数据时需特别注意。

三、DataFrame的核心属性与操作

创建DataFrame后,有几个常用属性需要掌握:

  • shape:返回行数和列数,例如(5, 3)表示5行3列。
  • columns:返回所有列名,类型为Index。
  • index:返回行索引,类型为Index。
  • dtypes:返回每列的数据类型,类似于TypeScript中的类型检查。
  • values:返回底层NumPy数组,便于与科学计算库交互。

实战技巧:使用df.head()可以快速预览前5行数据,df.info()则能展示数据概览(包括非空值数量、数据类型等),这在数据探索阶段非常有用。

[AFFILIATE_SLOT_1]

四、DataFrame与其他编程语言的对比

如果你有TypeScript、Go、C++或JavaScript背景,理解DataFrame可以借助以下类比:

  • TypeScript:DataFrame类似于一个类型化的对象数组,每一列对应一个接口属性,行则是数组元素。
  • Go:DataFrame类似于[]struct,但提供了更丰富的内置方法(如聚合、过滤)。
  • C++:DataFrame类似于二维向量std::vector>,但支持列名访问和自动类型推断。
  • JavaScript:DataFrame类似于一个对象数组,但Pandas的索引和向量化操作效率远高于手动循环。

核心优势:Pandas DataFrame将数据操作从“逐行循环”提升到“向量化操作”,性能接近C++底层实现,而语法接近Python的优雅。

五、常见问题与解决方案

Q1:创建DataFrame时,列名包含空格怎么办?
A:使用字典键时直接包含空格即可,但后续访问需要使用df['column name'],而非常用的df.column_name。推荐使用下划线命名法避免歧义。

Q2:如何从CSV文件创建DataFrame?
A:使用pd.read_csv('file.csv'),这是最常用的方式。Pandas支持多种文件格式(Excel、JSON、SQL等)。

Q3:为什么我的DataFrame显示为省略号?
A:默认Pandas只显示前60行。使用pd.set_option('display.max_rows', None)可以显示全部行,但慎用于大数据集。

[AFFILIATE_SLOT_2]

六、总结

通过本文,你已经掌握了DataFrame的核心概念与三种创建方法:从Series组合、从字典构建以及从文件导入。理解DataFrame的结构(行索引、列名、数据类型)是进行数据分析的第一步。与TypeScript、Go、C++、JavaScript等语言相比,Python的Pandas提供了更高效的数据操作方式。下一篇文章,我们将深入DataFrame的索引、切片与筛选操作,敬请期待!