数据结构
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
小结
| 特性 | Series | DataFrame |
|---|---|---|
| 维度 | 一维 | 二维 |
| 索引 | 单索引 | 行索引 + 列索引 |
| 数据类型 | 单一类型 | 每列可不同 |
| 创建方式 | 列表、字典、标量 | 字典、数组、Series |
| 选择数据 | [], loc, iloc | [], loc, iloc |
练习
- 创建一个包含 5 个学生信息的 Series,索引为学生姓名,值为分数
- 创建一个 5x4 的 DataFrame,包含姓名、年龄、城市、分数四列
- 练习使用 loc 和 iloc 选择数据
- 添加一列"等级",根据分数计算(>=90: A, >=80: B, >=60: C, <60: D)
下一步
掌握了数据结构后,让我们学习如何 读取和保存数据!