行莫
行莫
发布于 2025-11-18 / 2 阅读
0
0

Pandas 数据处理详解

Pandas 数据处理详解

引言

Pandas 是 Python 中最强大的数据处理和分析库之一,它提供了高效、灵活的数据结构,让数据分析变得简单直观。无论是处理 Excel 表格、CSV 文件,还是进行复杂的数据分析,Pandas 都是不可或缺的工具。

本教程特点:

  • 每个概念都配有可直接运行的代码示例
  • 代码可以直接复制到 Python 解释器中执行
  • 循序渐进,从基础到高级
  • 包含实际应用场景和最佳实践

学习建议:

  1. 阅读每个示例代码
  2. 复制代码到 Python 解释器或 Jupyter Notebook 中运行
  3. 尝试修改代码,观察结果变化
  4. 完成每个部分的练习

安装 Pandas:

pip install pandas

第一部分:Pandas 基础

1. 什么是 Pandas?

Pandas 提供了两个核心数据结构:

  • Series:一维数据,类似带标签的数组
  • DataFrame:二维数据,类似 Excel 表格

2. 导入 Pandas

# 示例 1:导入 Pandas
import pandas as pd
import numpy as np

# 查看 Pandas 版本
print(f"Pandas 版本:{pd.__version__}")

运行结果:

Pandas 版本:2.0.0

第二部分:Series(序列)

1. 创建 Series

# 示例 2:创建 Series
import pandas as pd

# 方法1:从列表创建
s1 = pd.Series([1, 3, 5, 7, 9])
print("从列表创建:")
print(s1)
print()

# 方法2:指定索引
s2 = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print("指定索引:")
print(s2)
print()

# 方法3:从字典创建
s3 = pd.Series({'苹果': 5, '香蕉': 3, '橙子': 8})
print("从字典创建:")
print(s3)
print()

# 方法4:指定数据类型
s4 = pd.Series([1.5, 2.5, 3.5], dtype='float32')
print("指定数据类型:")
print(s4)
print(f"数据类型:{s4.dtype}")

运行结果:

从列表创建:
0    1
1    3
2    5
3    7
4    9
dtype: int64

指定索引:
a    10
b    20
c    30
d    40
dtype: int64

从字典创建:
苹果    5
香蕉    3
橙子    8
dtype: int64

指定数据类型:
0    1.5
1    2.5
2    3.5
dtype: float32
数据类型:float32

2. Series 的基本操作

# 示例 3:Series 基本操作
import pandas as pd

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

# 访问元素
print(f"第一个元素:{s[0]}")
print(f"通过索引访问:{s['a']}")
print(f"前三个元素:\n{s[:3]}")
print()

# 基本属性
print(f"索引:{s.index}")
print(f"值:{s.values}")
print(f"长度:{len(s)}")
print(f"大小:{s.size}")
print(f"形状:{s.shape}")
print()

# 统计信息
print("统计信息:")
print(f"平均值:{s.mean()}")
print(f"总和:{s.sum()}")
print(f"最大值:{s.max()}")
print(f"最小值:{s.min()}")
print(f"标准差:{s.std()}")
print()

# 布尔索引
print("大于30的元素:")
print(s[s > 30])

运行结果:

第一个元素:10
通过索引访问:10
前三个元素:
a    10
b    20
c    30
dtype: int64

索引:Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
值:[10 20 30 40 50]
长度:5
大小:5
形状:(5,)

统计信息:
平均值:30.0
总和:150
最大值:50
最小值:10
标准差:15.811388300841896

大于30的元素:
d    40
e    50
dtype: int64

第三部分:DataFrame(数据框)

1. 创建 DataFrame

# 示例 4:创建 DataFrame
import pandas as pd

# 方法1:从字典创建
data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df1 = pd.DataFrame(data)
print("从字典创建:")
print(df1)
print()

# 方法2:从列表的列表创建
data2 = [
    ['张三', 25, '北京', 8000],
    ['李四', 30, '上海', 12000],
    ['王五', 28, '广州', 10000]
]
df2 = pd.DataFrame(data2, columns=['姓名', '年龄', '城市', '工资'])
print("从列表创建:")
print(df2)
print()

# 方法3:从 NumPy 数组创建
import numpy as np
arr = np.random.randn(3, 4)
df3 = pd.DataFrame(arr, columns=['A', 'B', 'C', 'D'])
print("从 NumPy 数组创建:")
print(df3)
print()

# 方法4:创建空 DataFrame
df4 = pd.DataFrame(columns=['姓名', '年龄'])
print("空 DataFrame:")
print(df4)

运行结果:

从字典创建:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000
2  王五  28  广州  10000
3  赵六  35  深圳  15000

从列表创建:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000
2  王五  28  广州  10000

从 NumPy 数组创建:
          A         B         C         D
0  0.374540  1.950714  0.731994  0.598658
1  0.156019  0.155995  0.058084  0.866176
2  0.601115  0.708073  0.020584  0.969910

空 DataFrame:
Empty DataFrame
Columns: [姓名, 年龄]
Index: [0, 1, 2]

2. DataFrame 的基本属性

# 示例 5:DataFrame 基本属性
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# 基本信息
print("DataFrame 形状:")
print(df.shape)  # (行数, 列数)
print()

print("列名:")
print(df.columns)
print()

print("索引:")
print(df.index)
print()

print("数据类型:")
print(df.dtypes)
print()

print("基本信息:")
print(df.info())
print()

print("统计摘要:")
print(df.describe())
print()

print("前几行:")
print(df.head(2))
print()

print("后几行:")
print(df.tail(2))

运行结果:

DataFrame 形状:
(4, 4)

列名:
Index(['姓名', '年龄', '城市', '工资'], dtype='object')

索引:
RangeIndex(start=0, stop=4, step=1)

数据类型:
姓名    object
年龄     int64
城市    object
工资     int64
dtype: object

基本信息:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   姓名     4 non-null      object
 1   年龄     4 non-null      int64
 2   城市     4 non-null      object
 3   工资     4 non-null      int64
dtypes: int64(2), object(2)
memory usage: 256.0+ bytes
None

统计摘要:
           年龄         工资
count   4.000000     4.000000
mean   29.500000 11250.000000
std     4.201190  3041.381265
min    25.000000  8000.000000
25%    27.250000  9500.000000
50%    29.000000 11000.000000
75%    31.750000 12750.000000
max    35.000000 15000.000000

前几行:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000

后几行:
   姓名  年龄  城市     工资
2  王五  28  广州  10000
3  赵六  35  深圳  15000

第四部分:数据读取和写入

1. 读取 CSV 文件

# 示例 6:读取和写入 CSV 文件
import pandas as pd

# 首先创建一个示例 CSV 文件
data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# 保存为 CSV
df.to_csv('employees.csv', index=False, encoding='utf-8-sig')
print("已创建 employees.csv 文件")
print()

# 读取 CSV 文件
df_read = pd.read_csv('employees.csv', encoding='utf-8-sig')
print("读取的 CSV 文件:")
print(df_read)
print()

# 读取时指定参数
df_read2 = pd.read_csv('employees.csv', 
                       encoding='utf-8-sig',
                       usecols=['姓名', '年龄'],  # 只读取指定列
                       nrows=2)  # 只读取前2行
print("读取指定列和前2行:")
print(df_read2)

运行结果:

已创建 employees.csv 文件

读取的 CSV 文件:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000
2  王五  28  广州  10000
3  赵六  35  深圳  15000

读取指定列和前2行:
   姓名  年龄
0  张三  25
1  李四  30

2. 读取 Excel 文件

# 示例 7:读取和写入 Excel 文件
import pandas as pd

# 创建数据
data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

# 保存为 Excel
df.to_excel('employees.xlsx', index=False, sheet_name='员工信息')
print("已创建 employees.xlsx 文件")
print()

# 读取 Excel 文件
df_excel = pd.read_excel('employees.xlsx', sheet_name='员工信息')
print("读取的 Excel 文件:")
print(df_excel)
print()

# 读取多个工作表
# 假设有多个工作表
with pd.ExcelWriter('multi_sheet.xlsx') as writer:
    df.to_excel(writer, sheet_name='Sheet1', index=False)
    df.to_excel(writer, sheet_name='Sheet2', index=False)

# 读取所有工作表
excel_file = pd.ExcelFile('multi_sheet.xlsx')
print("工作表名称:")
print(excel_file.sheet_names)

注意:读取 Excel 文件需要安装 openpyxlxlrd

pip install openpyxl

3. 读取 JSON 文件

# 示例 8:读取和写入 JSON 文件
import pandas as pd

# 创建数据
data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

# 保存为 JSON
df.to_json('employees.json', orient='records', force_ascii=False)
print("已创建 employees.json 文件")
print()

# 读取 JSON 文件
df_json = pd.read_json('employees.json')
print("读取的 JSON 文件:")
print(df_json)

第五部分:数据选择和索引

1. 选择列

# 示例 9:选择列
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# 方法1:使用列名(返回 Series)
print("选择单列(返回 Series):")
print(df['姓名'])
print()

# 方法2:使用点号(仅当列名是有效的 Python 标识符时)
print("使用点号选择列:")
print(df.姓名)
print()

# 方法3:选择多列(返回 DataFrame)
print("选择多列:")
print(df[['姓名', '年龄']])
print()

# 方法4:使用 loc 选择列
print("使用 loc 选择列:")
print(df.loc[:, '姓名':'城市'])  # 选择从'姓名'到'城市'的所有列

运行结果:

选择单列(返回 Series):
0    张三
1    李四
2    王五
3    赵六
Name: 姓名, dtype: object

使用点号选择列:
0    张三
1    李四
2    王五
3    赵六
Name: 姓名, dtype: object

选择多列:
   姓名  年龄
0  张三  25
1  李四  30
2  王五  28
3  赵六  35

使用 loc 选择列:
   姓名  年龄  城市
0  张三  25  北京
1  李四  30  上海
2  王五  28  广州
3  赵六  35  深圳

2. 选择行

# 示例 10:选择行
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# 方法1:使用索引位置(iloc)
print("选择第一行:")
print(df.iloc[0])
print()

print("选择前两行:")
print(df.iloc[0:2])
print()

print("选择最后一行:")
print(df.iloc[-1])
print()

# 方法2:使用标签索引(loc)
print("使用 loc 选择行:")
print(df.loc[0:2])  # 注意:loc 包含结束位置
print()

# 方法3:使用布尔索引
print("选择年龄大于28的行:")
print(df[df['年龄'] > 28])
print()

print("选择工资大于10000的行:")
print(df[df['工资'] > 10000])
print()

# 方法4:多条件筛选
print("多条件筛选(年龄>25 且 工资>9000):")
print(df[(df['年龄'] > 25) & (df['工资'] > 9000)])

运行结果:

选择第一行:
姓名    张三
年龄    25
城市    北京
工资    8000
Name: 0, dtype: object

选择前两行:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000

选择最后一行:
姓名    赵六
年龄    35
城市    深圳
工资   15000
Name: 3, dtype: object

使用 loc 选择行:
   姓名  年龄  城市     工资
0  张三  25  北京   8000
1  李四  30  上海  12000
2  王五  28  广州  10000

选择年龄大于28的行:
   姓名  年龄  城市     工资
1  李四  30  上海  12000
3  赵六  35  深圳  15000

选择工资大于10000的行:
   姓名  年龄  城市     工资
1  李四  30  上海  12000
3  赵六  35  深圳  15000

多条件筛选(年龄>25 且 工资>9000):
   姓名  年龄  城市     工资
1  李四  30  上海  12000
2  王五  28  广州  10000
3  赵六  35  深圳  15000

3. 选择行和列(loc 和 iloc)

# 示例 11:使用 loc 和 iloc 选择数据
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# loc:基于标签的选择
print("loc - 选择特定行和列:")
print(df.loc[0, '姓名'])  # 单个值
print()

print(df.loc[0:2, ['姓名', '年龄']])  # 多行多列
print()

# iloc:基于位置的选择
print("iloc - 基于位置选择:")
print(df.iloc[0, 0])  # 第一个元素
print()

print(df.iloc[0:2, 0:2])  # 前两行前两列
print()

# 使用条件选择
print("条件选择:")
print(df.loc[df['年龄'] > 28, ['姓名', '工资']])

运行结果:

loc - 选择特定行和列:
张三

   姓名  年龄
0  张三  25
1  李四  30
2  王五  28

iloc - 基于位置选择:
张三

   姓名  年龄
0  张三  25
1  李四  30

条件选择:
   姓名     工资
1  李四  12000
3  赵六  15000

第六部分:数据清洗

1. 处理缺失值

# 示例 12:处理缺失值
import pandas as pd
import numpy as np

# 创建包含缺失值的数据
data = {
    '姓名': ['张三', '李四', '王五', '赵六', '钱七'],
    '年龄': [25, 30, None, 35, 28],
    '城市': ['北京', '上海', None, '深圳', '杭州'],
    '工资': [8000, 12000, 10000, None, 9000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 检查缺失值
print("检查缺失值:")
print(df.isnull())
print()

print("每列缺失值数量:")
print(df.isnull().sum())
print()

# 删除包含缺失值的行
print("删除包含缺失值的行:")
df_dropna = df.dropna()
print(df_dropna)
print()

# 填充缺失值
print("填充缺失值:")
df_filled = df.fillna({
    '年龄': df['年龄'].mean(),
    '城市': '未知',
    '工资': df['工资'].median()
})
print(df_filled)
print()

# 前向填充
print("前向填充:")
df_ffill = df.fillna(method='ffill')
print(df_ffill)

运行结果:

原始数据:
   姓名    年龄  城市     工资
0  张三  25.0  北京  8000.0
1  李四  30.0  上海  12000.0
2  王五   NaN  None  10000.0
3  赵六  35.0  深圳     NaN
4  钱七  28.0  杭州  9000.0

检查缺失值:
    姓名    年龄    城市    工资
0  False  False  False  False
1  False  False  False  False
2  False   True   True  False
3  False  False  False   True
4  False  False  False  False

每列缺失值数量:
姓名    0
年龄    1
城市    1
工资    1
dtype: int64

删除包含缺失值的行:
   姓名    年龄  城市     工资
0  张三  25.0  北京  8000.0
1  李四  30.0  上海  12000.0
4  钱七  28.0  杭州  9000.0

填充缺失值:
   姓名    年龄  城市     工资
0  张三  25.0  北京  8000.0
1  李四  30.0  上海  12000.0
2  王五  29.5  未知  10000.0
3  赵六  35.0  深圳  10000.0
4  钱七  28.0  杭州  9000.0

前向填充:
   姓名    年龄  城市     工资
0  张三  25.0  北京  8000.0
1  李四  30.0  上海  12000.0
2  王五  30.0  上海  10000.0
3  赵六  35.0  深圳  10000.0
4  钱七  28.0  杭州  9000.0

2. 处理重复值

# 示例 13:处理重复值
import pandas as pd

# 创建包含重复值的数据
data = {
    '姓名': ['张三', '李四', '王五', '张三', '李四'],
    '年龄': [25, 30, 28, 25, 30],
    '工资': [8000, 12000, 10000, 8000, 12000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 检查重复值
print("检查重复行:")
print(df.duplicated())
print()

print("重复行数量:")
print(df.duplicated().sum())
print()

# 删除重复值
print("删除重复行:")
df_unique = df.drop_duplicates()
print(df_unique)
print()

# 基于特定列删除重复值
print("基于'姓名'列删除重复:")
df_unique_name = df.drop_duplicates(subset=['姓名'])
print(df_unique_name)

运行结果:

原始数据:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000
3  张三  25   8000
4  李四  30  12000

检查重复行:
0    False
1    False
2    False
3     True
4     True
dtype: bool

重复行数量:
2

删除重复行:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000

基于'姓名'列删除重复:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000

3. 数据类型转换

# 示例 14:数据类型转换
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': ['25', '30', '28'],  # 字符串类型
    '工资': [8000.5, 12000.3, 10000.7]
}
df = pd.DataFrame(data)

print("原始数据类型:")
print(df.dtypes)
print()

# 转换数据类型
df['年龄'] = df['年龄'].astype(int)
df['工资'] = df['工资'].astype(int)

print("转换后的数据类型:")
print(df.dtypes)
print()

print("转换后的数据:")
print(df)

第七部分:数据操作

1. 添加和删除列

# 示例 15:添加和删除列
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 添加新列
df['城市'] = ['北京', '上海', '广州']
print("添加'城市'列:")
print(df)
print()

# 使用计算添加列
df['年薪'] = df['工资'] * 12
print("添加'年薪'列(计算列):")
print(df)
print()

# 删除列
df_dropped = df.drop('年薪', axis=1)
print("删除'年薪'列:")
print(df_dropped)
print()

# 删除多列
df_dropped2 = df.drop(['城市', '年薪'], axis=1)
print("删除多列:")
print(df_dropped2)

运行结果:

原始数据:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000

添加'城市'列:
   姓名  年龄     工资  城市
0  张三  25   8000  北京
1  李四  30  12000  上海
2  王五  28  10000  广州

添加'年薪'列(计算列):
   姓名  年龄     工资  城市     年薪
0  张三  25   8000  北京   96000
1  李四  30  12000  上海  144000
2  王五  28  10000  广州  120000

删除'年薪'列:
   姓名  年龄     工资  城市
0  张三  25   8000  北京
1  李四  30  12000  上海
2  王五  28  10000  广州

删除多列:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000

2. 添加和删除行

# 示例 16:添加和删除行
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 添加新行(使用 append,已弃用,推荐使用 concat)
new_row = pd.DataFrame({'姓名': ['赵六'], '年龄': [35], '工资': [15000]})
df = pd.concat([df, new_row], ignore_index=True)
print("添加新行:")
print(df)
print()

# 删除行
df_dropped = df.drop(0)  # 删除第一行
print("删除第一行:")
print(df_dropped)
print()

# 删除多行
df_dropped2 = df.drop([0, 2])
print("删除多行:")
print(df_dropped2)

3. 排序

# 示例 17:数据排序
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 按单列排序
print("按年龄升序排序:")
print(df.sort_values('年龄'))
print()

print("按工资降序排序:")
print(df.sort_values('工资', ascending=False))
print()

# 按多列排序
print("按年龄和工资排序:")
print(df.sort_values(['年龄', '工资'], ascending=[True, False]))
print()

# 重置索引
df_sorted = df.sort_values('年龄')
df_sorted = df_sorted.reset_index(drop=True)
print("排序后重置索引:")
print(df_sorted)

运行结果:

原始数据:
   姓名  年龄     工资
0  张三  25   8000
1  李四  30  12000
2  王五  28  10000
3  赵六  35  15000

按年龄升序排序:
   姓名  年龄     工资
0  张三  25   8000
2  王五  28  10000
1  李四  30  12000
3  赵六  35  15000

按工资降序排序:
   姓名  年龄     工资
3  赵六  35  15000
1  李四  30  12000
2  王五  28  10000
0  张三  25   8000

按年龄和工资排序:
   姓名  年龄     工资
0  张三  25   8000
2  王五  28  10000
1  李四  30  12000
3  赵六  35  15000

排序后重置索引:
   姓名  年龄     工资
0  张三  25   8000
1  王五  28  10000
2  李四  30  12000
3  赵六  35  15000

第八部分:数据分组和聚合

1. 分组操作(groupby)

# 示例 18:分组操作
import pandas as pd

data = {
    '部门': ['销售', '销售', '技术', '技术', '销售', '技术'],
    '姓名': ['张三', '李四', '王五', '赵六', '钱七', '孙八'],
    '工资': [8000, 10000, 12000, 15000, 9000, 13000]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 按部门分组
grouped = df.groupby('部门')

print("分组后的组:")
for name, group in grouped:
    print(f"\n{name} 部门:")
    print(group)
print()

# 分组聚合
print("各部门平均工资:")
print(grouped['工资'].mean())
print()

print("各部门工资总和:")
print(grouped['工资'].sum())
print()

print("各部门员工数量:")
print(grouped.size())
print()

# 多列聚合
print("多列聚合:")
print(grouped.agg({
    '工资': ['mean', 'sum', 'max', 'min']
}))

运行结果:

原始数据:
   部门  姓名     工资
0  销售  张三   8000
1  销售  李四  10000
2  技术  王五  12000
3  技术  赵六  15000
4  销售  钱七   9000
5  技术  孙八  13000

分组后的组:

销售 部门:
   部门  姓名     工资
0  销售  张三   8000
1  销售  李四  10000
4  销售  钱七   9000

技术 部门:
   部门  姓名     工资
2  技术  王五  12000
3  技术  赵六  15000
5  技术  孙八  13000

各部门平均工资:
部门
技术    13333.333333
销售     9000.000000
Name: 工资, dtype: float64

各部门工资总和:
部门
技术    40000
销售    27000
Name: 工资, dtype: int64

各部门员工数量:
部门
技术    3
销售    3
dtype: int64

多列聚合:
           工资
         mean      sum    max    min
部门                                
技术  13333.333333  40000  15000  12000
销售   9000.000000  27000  10000   8000

2. 透视表(pivot_table)

# 示例 19:透视表
import pandas as pd

data = {
    '日期': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02', '2024-01-03', '2024-01-03'],
    '产品': ['A', 'B', 'A', 'B', 'A', 'B'],
    '销售额': [1000, 1500, 1200, 1800, 1100, 1600]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 创建透视表
pivot = pd.pivot_table(df, 
                       values='销售额', 
                       index='日期', 
                       columns='产品', 
                       aggfunc='sum')
print("透视表:")
print(pivot)
print()

# 多值透视表
data2 = {
    '日期': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
    '产品': ['A', 'B', 'A', 'B'],
    '销售额': [1000, 1500, 1200, 1800],
    '数量': [10, 15, 12, 18]
}
df2 = pd.DataFrame(data2)

pivot2 = pd.pivot_table(df2,
                        values=['销售额', '数量'],
                        index='日期',
                        columns='产品',
                        aggfunc='sum')
print("多值透视表:")
print(pivot2)

运行结果:

原始数据:
         日期  产品  销售额
0  2024-01-01  A  1000
1  2024-01-01  B  1500
2  2024-01-02  A  1200
3  2024-01-02  B  1800
4  2024-01-03  A  1100
5  2024-01-03  B  1600

透视表:
产品            A     B
日期                    
2024-01-01  1000  1500
2024-01-02  1200  1800
2024-01-03  1100  1600

多值透视表:
         销售额        数量      
产品          A     B    A   B
日期                          
2024-01-01  1000  1500  10  15
2024-01-02  1200  1800  12  18

第九部分:数据合并

1. 合并(merge)

# 示例 20:数据合并
import pandas as pd

# 创建两个 DataFrame
df1 = pd.DataFrame({
    '员工ID': [1, 2, 3, 4],
    '姓名': ['张三', '李四', '王五', '赵六'],
    '部门ID': [101, 102, 101, 103]
})

df2 = pd.DataFrame({
    '部门ID': [101, 102, 103, 104],
    '部门名称': ['销售部', '技术部', '财务部', '人事部']
})

print("DataFrame 1:")
print(df1)
print()

print("DataFrame 2:")
print(df2)
print()

# 内连接(inner join)
print("内连接:")
df_inner = pd.merge(df1, df2, on='部门ID', how='inner')
print(df_inner)
print()

# 左连接(left join)
print("左连接:")
df_left = pd.merge(df1, df2, on='部门ID', how='left')
print(df_left)
print()

# 外连接(outer join)
print("外连接:")
df_outer = pd.merge(df1, df2, on='部门ID', how='outer')
print(df_outer)

运行结果:

DataFrame 1:
   员工ID  姓名  部门ID
0      1  张三    101
1      2  李四    102
2      3  王五    101
3      4  赵六    103

DataFrame 2:
   部门ID  部门名称
0    101   销售部
1    102   技术部
2    103   财务部
3    104   人事部

内连接:
   员工ID  姓名  部门ID  部门名称
0      1  张三    101   销售部
1      2  李四    102   技术部
2      3  王五    101   销售部
3      4  赵六    103   财务部

左连接:
   员工ID  姓名  部门ID  部门名称
0      1  张三    101   销售部
1      2  李四    102   技术部
2      3  王五    101   销售部
3      4  赵六    103   财务部

外连接:
   员工ID  姓名  部门ID  部门名称
0    1.0  张三  101.0   销售部
1    2.0  李四  102.0   技术部
2    3.0  王五  101.0   销售部
3    4.0  赵六  103.0   财务部
4    NaN  NaN  104.0   人事部

2. 连接(concat)

# 示例 21:连接操作
import pandas as pd

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

df2 = pd.DataFrame({
    'A': [7, 8, 9],
    'B': [10, 11, 12]
})

print("DataFrame 1:")
print(df1)
print()

print("DataFrame 2:")
print(df2)
print()

# 垂直连接(沿行方向)
print("垂直连接:")
df_concat = pd.concat([df1, df2], ignore_index=True)
print(df_concat)
print()

# 水平连接(沿列方向)
print("水平连接:")
df_concat_h = pd.concat([df1, df2], axis=1)
print(df_concat_h)

第十部分:时间序列处理

1. 创建时间序列

# 示例 22:时间序列处理
import pandas as pd

# 创建日期范围
dates = pd.date_range('2024-01-01', periods=7, freq='D')
print("日期范围:")
print(dates)
print()

# 创建时间序列数据
ts = pd.Series([100, 105, 110, 108, 112, 115, 120], index=dates)
print("时间序列:")
print(ts)
print()

# 创建带日期的 DataFrame
df = pd.DataFrame({
    '日期': pd.date_range('2024-01-01', periods=5, freq='D'),
    '销售额': [1000, 1200, 1100, 1300, 1250]
})

print("带日期的 DataFrame:")
print(df)
print()

# 将日期列设置为索引
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
print("日期作为索引:")
print(df)

运行结果:

日期范围:
DatetimeIndex(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04',
               '2024-01-05', '2024-01-06', '2024-01-07'],
              dtype='datetime64[ns]', freq='D')

时间序列:
2024-01-01    100
2024-01-02    105
2024-01-03    110
2024-01-04    108
2024-01-05    112
2024-01-06    115
2024-01-07    120
Freq: D, dtype: int64

带日期的 DataFrame:
          日期  销售额
0 2024-01-01  1000
1 2024-01-02  1200
2 2024-01-03  1100
3 2024-01-04  1300
4 2024-01-05  1250

日期作为索引:
            销售额
日期              
2024-01-01  1000
2024-01-02  1200
2024-01-03  1100
2024-01-04  1300
2024-01-05  1250

2. 时间序列操作

# 示例 23:时间序列操作
import pandas as pd

# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=30, freq='D')
df = pd.DataFrame({
    '日期': dates,
    '销售额': range(1000, 1030)
})
df.set_index('日期', inplace=True)

print("原始数据(前5行):")
print(df.head())
print()

# 按周重采样
print("按周求和:")
weekly = df.resample('W').sum()
print(weekly)
print()

# 按月重采样
print("按月求和:")
monthly = df.resample('M').sum()
print(monthly)
print()

# 移动平均
df['移动平均7天'] = df['销售额'].rolling(window=7).mean()
print("添加7天移动平均:")
print(df.head(10))

第十一部分:实际应用示例

1. 学生成绩分析系统

# 示例 24:学生成绩分析系统
import pandas as pd
import numpy as np

# 创建学生成绩数据
np.random.seed(42)
data = {
    '学号': [f'2024{i:04d}' for i in range(1, 21)],
    '姓名': [f'学生{i}' for i in range(1, 21)],
    '数学': np.random.randint(60, 101, 20),
    '英语': np.random.randint(60, 101, 20),
    '物理': np.random.randint(60, 101, 20),
    '化学': np.random.randint(60, 101, 20)
}
df = pd.DataFrame(data)

# 计算总分和平均分
df['总分'] = df[['数学', '英语', '物理', '化学']].sum(axis=1)
df['平均分'] = df['总分'] / 4

# 添加等级
def get_grade(avg):
    if avg >= 90:
        return '优秀'
    elif avg >= 80:
        return '良好'
    elif avg >= 70:
        return '中等'
    elif avg >= 60:
        return '及格'
    else:
        return '不及格'

df['等级'] = df['平均分'].apply(get_grade)

print("学生成绩表:")
print(df)
print()

# 统计分析
print("=" * 50)
print("统计分析")
print("=" * 50)

print("\n各科平均分:")
print(df[['数学', '英语', '物理', '化学']].mean())
print()

print("\n各科最高分:")
print(df[['数学', '英语', '物理', '化学']].max())
print()

print("\n各等级人数:")
print(df['等级'].value_counts())
print()

print("\n平均分排名前5:")
print(df.nlargest(5, '平均分')[['姓名', '平均分', '等级']])

运行结果:

学生成绩表:
       学号    姓名  数学  英语  物理  化学  总分   平均分  等级
0   20240001  学生1   92   75   95   78  340  85.00  良好
1   20240002  学生2   64   88   70   75  297  74.25  中等
2   20240003  学生3   67   78   95   88  328  82.00  良好
...(省略部分输出)

统计分析
==================================================

各科平均分:
数学    77.85
英语    78.20
物理    78.10
化学    78.15
dtype: float64

各科最高分:
数学    100
英语    99
物理    99
化学    99
dtype: int64

各等级人数:
良好    8
中等    6
优秀    4
及格    2
dtype: int64

平均分排名前5:
     姓名   平均分  等级
0   学生1  85.00  良好
3   学生4  84.50  良好
...(省略部分输出)

2. 销售数据分析

# 示例 25:销售数据分析
import pandas as pd
import numpy as np

# 创建销售数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=100, freq='D')
data = {
    '日期': dates,
    '产品': np.random.choice(['A', 'B', 'C'], 100),
    '销售额': np.random.randint(1000, 5000, 100),
    '数量': np.random.randint(10, 100, 100)
}
df = pd.DataFrame(data)

# 计算单价
df['单价'] = df['销售额'] / df['数量']

print("销售数据(前10行):")
print(df.head(10))
print()

# 按产品分组分析
print("=" * 50)
print("按产品分析")
print("=" * 50)

product_analysis = df.groupby('产品').agg({
    '销售额': ['sum', 'mean', 'count'],
    '数量': 'sum',
    '单价': 'mean'
}).round(2)

print(product_analysis)
print()

# 按日期分析
print("=" * 50)
print("按日期分析(按月)")
print("=" * 50)

df['月份'] = df['日期'].dt.month
monthly_analysis = df.groupby('月份').agg({
    '销售额': 'sum',
    '数量': 'sum'
}).round(2)

print(monthly_analysis)

第十二部分:高级功能

1. 应用函数(apply)

# 示例 26:使用 apply 应用函数
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

# 应用函数到列
def calculate_tax(salary):
    if salary > 10000:
        return salary * 0.1
    else:
        return salary * 0.05

df['税费'] = df['工资'].apply(calculate_tax)
df['税后工资'] = df['工资'] - df['税费']

print("应用函数后的数据:")
print(df)
print()

# 应用函数到行
def get_info(row):
    return f"{row['姓名']}{row['年龄']}岁,工资{row['工资']}元"

df['信息'] = df.apply(get_info, axis=1)
print("添加信息列:")
print(df[['姓名', '信息']])

运行结果:

应用函数后的数据:
   姓名  年龄     工资     税费  税后工资
0  张三  25   8000  400.0   7600.0
1  李四  30  12000 1200.0  10800.0
2  王五  28  10000  500.0   9500.0

添加信息列:
   姓名                   信息
0  张三  张三,25岁,工资8000元
1  李四  李四,30岁,工资12000元
2  王五  王五,28岁,工资10000元

2. 条件操作

# 示例 27:条件操作
import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '工资': [8000, 12000, 10000, 15000]
}
df = pd.DataFrame(data)

# 使用 where
df['高薪'] = df['工资'].where(df['工资'] > 10000, '否')
print("使用 where:")
print(df)
print()

# 使用 np.where
import numpy as np
df['等级'] = np.where(df['工资'] > 10000, '高', '低')
print("使用 np.where:")
print(df[['姓名', '工资', '等级']])

3. 数据透视和重塑

# 示例 28:数据重塑
import pandas as pd

# 创建数据
data = {
    '日期': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
    '产品': ['A', 'B', 'A', 'B'],
    '销售额': [1000, 1500, 1200, 1800]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 透视
pivot = df.pivot(index='日期', columns='产品', values='销售额')
print("透视后:")
print(pivot)
print()

# 堆叠和取消堆叠
stacked = pivot.stack()
print("堆叠:")
print(stacked)
print()

unstacked = stacked.unstack()
print("取消堆叠:")
print(unstacked)

第十三部分:性能优化和最佳实践

1. 使用向量化操作

# 示例 29:向量化操作 vs 循环
import pandas as pd
import numpy as np
import time

# 创建大数据集
df = pd.DataFrame({
    'A': np.random.randn(100000),
    'B': np.random.randn(100000)
})

# 方法1:使用循环(慢)
start = time.time()
result1 = []
for i in range(len(df)):
    result1.append(df.iloc[i]['A'] * df.iloc[i]['B'])
time1 = time.time() - start

# 方法2:使用向量化操作(快)
start = time.time()
result2 = df['A'] * df['B']
time2 = time.time() - start

print(f"循环方法耗时:{time1:.4f} 秒")
print(f"向量化方法耗时:{time2:.4f} 秒")
print(f"速度提升:{time1/time2:.2f} 倍")

2. 最佳实践

# 示例 30:最佳实践总结
import pandas as pd

# 1. 使用 copy() 避免意外修改原始数据
df1 = pd.DataFrame({'A': [1, 2, 3]})
df2 = df1.copy()  # 推荐
df2['A'] = [4, 5, 6]
print("原始数据未被修改:")
print(df1)
print()

# 2. 使用 inplace 参数
df = pd.DataFrame({'A': [1, 2, 3, 4, 5]})
df.drop([0, 1], inplace=True)  # 直接修改,不返回新对象
print("使用 inplace:")
print(df)
print()

# 3. 链式操作
data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '工资': [8000, 12000, 10000]
}
df = pd.DataFrame(data)

result = (df
          .query('年龄 > 25')  # 筛选
          .sort_values('工资', ascending=False)  # 排序
          .reset_index(drop=True))  # 重置索引

print("链式操作结果:")
print(result)

第十四部分:练习和总结

练习1:数据分析任务

# 练习1:完成以下任务
# 1. 创建一个包含学生信息的 DataFrame
# 2. 计算每个学生的平均分
# 3. 找出平均分最高的学生
# 4. 按班级分组,计算每班的平均分

# 在这里编写你的代码

练习2:数据清洗任务

# 练习2:完成以下任务
# 1. 创建一个包含缺失值的数据集
# 2. 处理缺失值(填充或删除)
# 3. 处理重复值
# 4. 数据类型转换

# 在这里编写你的代码

总结

核心概念:

  1. Series:一维数据结构
  2. DataFrame:二维数据结构
  3. 索引和选择:loc、iloc、布尔索引
  4. 数据清洗:处理缺失值、重复值
  5. 数据操作:添加、删除、排序
  6. 分组和聚合:groupby、透视表
  7. 数据合并:merge、concat
  8. 时间序列:日期处理、重采样

常用方法:

  • read_csv() / to_csv():CSV 文件读写
  • read_excel() / to_excel():Excel 文件读写
  • head() / tail():查看前后几行
  • describe():统计摘要
  • groupby():分组操作
  • merge() / concat():数据合并
  • apply():应用函数
  • pivot_table():创建透视表

最佳实践:

  1. 使用向量化操作而不是循环
  2. 使用 copy() 避免意外修改
  3. 合理使用 inplace 参数
  4. 利用链式操作提高代码可读性
  5. 处理大数据时注意内存使用

下一步学习建议:

  1. 学习更多 Pandas 高级功能
  2. 结合 Matplotlib 进行数据可视化
  3. 学习数据分析和统计方法
  4. 实践真实项目,处理实际数据
  5. 阅读 Pandas 官方文档

评论