跳到主要内容

数据结构

Pandas 提供了两种核心数据结构:Series(一维)和 DataFrame(二维)。理解这两种数据结构是掌握 Pandas 的基础。

Series

Series 是带有标签的一维数组,可以存储任何数据类型(整数、字符串、浮点数、Python 对象等)。

创建 Series

import pandas as pd
import numpy as np

# 从列表创建
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
# 输出:
# 0 1.0
# 1 3.0
# 2 5.0
# 3 NaN
# 4 6.0
# 5 8.0
# dtype: float64

# 指定索引
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
print(s)
# 输出:
# a 1
# b 2
# c 3
# d 4
# dtype: int64

# 从字典创建
s = pd.Series({'a': 1, 'b': 2, 'c': 3})
print(s)
# 输出:
# a 1
# b 2
# c 3
# dtype: int64

# 从标量值创建
s = pd.Series(5, index=['a', 'b', 'c', 'd'])
print(s)
# 输出:
# a 5
# b 5
# c 5
# d 5
# dtype: int64

Series 属性

s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])

# 基本属性
print(s.values) # 值数组: [10 20 30 40]
print(s.index) # 索引: Index(['a', 'b', 'c', 'd'], dtype='object')
print(s.dtype) # 数据类型: int64
print(s.shape) # 形状: (4,)
print(s.size) # 元素数量: 4
print(s.ndim) # 维度: 1
print(s.nbytes) # 字节数: 32

# 索引类型
print(type(s.index)) # <class 'pandas.core.indexes.base.Index'>

访问 Series 元素

s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])

# 使用标签索引
print(s['a']) # 10
print(s[['a', 'c']]) # 多个元素
# a 10
# c 30

# 使用位置索引
print(s[0]) # 10
print(s[0:3]) # 切片
# a 10
# b 20
# c 30

# 布尔索引
print(s[s > 25]) # c 30, d 40

# 使用 loc(按标签)
print(s.loc['a']) # 10
print(s.loc['a':'c']) # a 10, b 20, c 30

# 使用 iloc(按位置)
print(s.iloc[0]) # 10
print(s.iloc[0:3]) # a 10, b 20, c 30

Series 运算

s1 = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])

# 算术运算
print(s1 + 10) # 每个元素加 10
print(s1 * 2) # 每个元素乘 2
print(s1 ** 2) # 每个元素平方

# Series 之间的运算(按索引对齐)
print(s1 + s2)
# a 11
# b 22
# c 33
# d 44

# 索引不同时的对齐
s3 = pd.Series([1, 2, 3], index=['a', 'b', 'e'])
print(s1 + s3)
# a 2.0
# b 4.0
# c NaN
# d NaN
# e NaN

Series 常用方法

s = pd.Series([3, 1, 4, 1, 5, 9, 2, 6])

# 统计方法
print(s.count()) # 非空元素数量: 8
print(s.sum()) # 求和: 31
print(s.mean()) # 平均值: 3.875
print(s.std()) # 标准差
print(s.min()) # 最小值: 1
print(s.max()) # 最大值: 9
print(s.median()) # 中位数: 3.5

# 其他方法
print(s.unique()) # 唯一值: [3 1 4 5 9 2 6]
print(s.nunique()) # 唯一值数量: 7
print(s.value_counts()) # 值计数
# 1 2
# 3 1
# 4 1
# 5 1
# 9 1
# 2 1
# 6 1

print(s.sort_values()) # 排序
print(s.sort_index()) # 按索引排序

DataFrame

DataFrame 是带有标签的二维表格数据结构,是 Pandas 最常用的数据类型。可以将其想象为一个 Excel 表格或 SQL 表。

创建 DataFrame

import pandas as pd
import numpy as np

# 从字典创建(最常用)
df = pd.DataFrame({
'name': ['张三', '李四', '王五', '赵六'],
'age': [25, 30, 35, 28],
'city': ['北京', '上海', '广州', '深圳'],
'salary': [10000, 15000, 20000, 12000]
})
print(df)
# name age city salary
# 0 张三 25 北京 10000
# 1 李四 30 上海 15000
# 2 王五 35 广州 20000
# 3 赵六 28 深圳 12000

# 从列表字典创建
data = [
{'name': '张三', 'age': 25, 'city': '北京'},
{'name': '李四', 'age': 30, 'city': '上海'},
{'name': '王五', 'age': 35, 'city': '广州'}
]
df = pd.DataFrame(data)

# 从二维数组创建
df = pd.DataFrame(
np.random.randn(6, 4),
index=pd.date_range('20240101', periods=6),
columns=list('ABCD')
)
print(df)

# 从 Series 创建
df = pd.DataFrame({
'A': pd.Series([1, 2, 3]),
'B': pd.Series([4, 5, 6])
})

DataFrame 属性

df = pd.DataFrame({
'name': ['张三', '李四', '王五'],
'age': [25, 30, 35],
'salary': [10000, 15000, 20000]
})

# 基本属性
print(df.shape) # (3, 3) - 3行3列
print(df.columns) # Index(['name', 'age', 'salary'], dtype='object')
print(df.index) # RangeIndex(start=0, stop=3, step=1)
print(df.dtypes) # 每列的数据类型
print(df.values) # 返回 NumPy 数组
print(df.ndim) # 维度: 2
print(df.size) # 元素总数: 9

# 列数据类型
print(df.dtypes)
# name object
# age int64
# salary int64
# dtype: object

查看数据

df = pd.DataFrame({
'A': range(10),
'B': np.random.randn(10),
'C': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
})

# 查看前几行
print(df.head()) # 默认前5行
print(df.head(3)) # 前3行

# 查看后几行
print(df.tail()) # 默认后5行
print(df.tail(3)) # 后3行

# 查看信息
print(df.info()) # 数据类型和内存使用
print(df.describe()) # 数值列的统计摘要
print(df.describe(include='all')) # 所有列的统计

选择列

df = pd.DataFrame({
'name': ['张三', '李四', '王五'],
'age': [25, 30, 35],
'salary': [10000, 15000, 20000]
})

# 选择单列 - 返回 Series
print(df['name'])
# 0 张三
# 1 李四
# 2 王五
# Name: name, dtype: object

# 点号访问(仅当列名是有效标识符时)
print(df.name)

# 选择多列 - 返回 DataFrame
print(df[['name', 'salary']])
# name salary
# 0 张三 10000
# 1 李四 15000
# 2 王五 20000

选择行

df = pd.DataFrame({
'name': ['张三', '李四', '王五', '赵六'],
'age': [25, 30, 35, 28],
'city': ['北京', '上海', '广州', '深圳']
}, index=['a', 'b', 'c', 'd'])

# 使用 loc(按标签选择)
print(df.loc['a']) # 选择一行
print(df.loc['a':'c']) # 选择多行
print(df.loc['a', 'name']) # 选择特定元素
print(df.loc['a':'c', ['name', 'age']]) # 选择特定行列

# 使用 iloc(按位置选择)
print(df.iloc[0]) # 选择第一行
print(df.iloc[0:3]) # 选择前3行
print(df.iloc[0, 0]) # 选择第一行第一列
print(df.iloc[0:3, 0:2]) # 行列切片

# 条件选择
print(df[df['age'] > 28]) # age > 28 的行
print(df[(df['age'] > 25) & (df['city'] == '上海')]) # 多条件

添加和删除列

df = pd.DataFrame({
'name': ['张三', '李四', '王五'],
'age': [25, 30, 35]
})

# 添加新列
df['city'] = ['北京', '上海', '广州']
df['salary'] = [10000, 15000, 20000]

# 基于现有列计算新列
df['bonus'] = df['salary'] * 0.1
df['total'] = df['salary'] + df['bonus']

# 使用 assign 方法(返回新 DataFrame)
df2 = df.assign(tax=df['salary'] * 0.2)

# 删除列
df = df.drop('bonus', axis=1) # 返回新 DataFrame
df.drop('total', axis=1, inplace=True) # 原地修改
del df['city'] # 原地删除

print(df)

添加和删除行

df = pd.DataFrame({
'name': ['张三', '李四', '王五'],
'age': [25, 30, 35]
}, index=[0, 1, 2])

# 添加行
new_row = pd.DataFrame({'name': ['赵六'], 'age': [28]})
df = pd.concat([df, new_row], ignore_index=True)

# 或者使用 loc
df.loc[len(df)] = ['孙七', 40]

# 删除行
df = df.drop(0) # 删除索引为0的行
df = df.drop([1, 2]) # 删除多行

print(df)

Index 对象

Index 是 Pandas 中用于轴标签的对象,是不可变的。

# 创建 Index
idx = pd.Index([1, 2, 3, 4])
print(idx) # Int64Index([1, 2, 3, 4], dtype='int64')

# Index 属性
print(idx.dtype) # int64
print(idx.shape) # (4,)
print(idx.size) # 4
print(idx.nunique()) # 4

# Index 操作
idx2 = idx.append(pd.Index([5, 6])) # 追加
idx3 = idx.delete(0) # 删除
idx4 = idx.insert(0, 0) # 插入
idx5 = idx.drop(1) # 删除特定值

# 判断索引是否存在
print(1 in idx) # True
print(5 in idx) # False

小结

特性SeriesDataFrame
维度一维二维
索引单索引行索引 + 列索引
数据类型单一类型每列可不同
创建方式列表、字典、标量字典、数组、Series
选择数据[], loc, iloc[], loc, iloc

练习

  1. 创建一个包含 5 个学生信息的 Series,索引为学生姓名,值为分数
  2. 创建一个 5x4 的 DataFrame,包含姓名、年龄、城市、分数四列
  3. 练习使用 loc 和 iloc 选择数据
  4. 添加一列"等级",根据分数计算(>=90: A, >=80: B, >=60: C, <60: D)

下一步

掌握了数据结构后,让我们学习如何 读取和保存数据