Pandas 数据处理与分析

标签: #Python #Pandas #数据处理 #数据分析 #Series #DataFrame
学习周期:2 天 | 核心目标:掌握 Pandas 核心数据结构,能完成数据读取、清洗、筛选、分组聚合及合并操作


4.2 Pandas(数据处理与分析)

Pandas 是基于 NumPy 开发的 Python 数据处理与分析库,专为表格型数据(如 Excel、CSV 文件)设计,提供了简洁、高效的数据操作接口。核心优势:支持缺失值处理、灵活的筛选与分组、强大的合并与透视功能,是数据科学、AI 开发中数据预处理的核心工具。

安装与导入

pip install pandas
import pandas as pd
import numpy as np   # Pandas 依赖 NumPy,通常一起导入

4.2.1 Series(一维)与 DataFrame(二维)的创建

Series(一维数据结构)

Series 由“数据值(values)”和“索引(index)”组成的一维数组,类似带标签的数组。

# 从列表创建(默认整数索引)
s1 = pd.Series([10, 20, 30, 40, 50])

# 指定索引
s2 = pd.Series([10, 20, 30], index=['a', 'b', 'c'])

# 从字典创建(键为索引)
s3 = pd.Series({'name': '张三', 'age': 20, 'gender': '男'})

# 核心属性
print(s2.index)      # Index(['a', 'b', 'c'])
print(s2.values)     # [10 20 30]
print(s2.dtype)      # int64

DataFrame(二维表格)

DataFrame 由“行索引”、“列索引”和“数据”组成,可理解为多个 Series 共享同一索引。

# 方式1:从字典列表创建(最常用)
data = [
    {"name": "张三", "age": 20, "gender": "男", "score": 85},
    {"name": "李四", "age": 21, "gender": "女", "score": 92},
]
df1 = pd.DataFrame(data)

# 方式2:从字典创建(键为列名,值为列数据)
dict_data = {
    "name": ["张三", "李四"],
    "age": [20, 21],
    "score": [85, 92]
}
df2 = pd.DataFrame(dict_data)

# 方式3:从 NumPy 数组创建
import numpy as np
arr = np.array([[1, 2], [3, 4]])
df3 = pd.DataFrame(arr, columns=['A', 'B'], index=['行1', '行2'])

# 方式4:空 DataFrame(后续添加数据)
df4 = pd.DataFrame(columns=["name", "age"])

# 核心属性
print(df1.shape)      # (2, 4)
print(df1.columns)    # Index(['name', 'age', 'gender', 'score'])
print(df1.index)      # RangeIndex(start=0, stop=2, step=1)
print(df1.dtypes)     # 每列数据类型

4.2.2 数据读取:pd.read_csv()pd.read_excel()pd.read_json()

读取 CSV 文件

# 基础读取
df = pd.read_csv('data.csv')

# 常用参数
df = pd.read_csv(
    'data.csv',
    encoding='utf-8',          # 编码(中文常用 utf-8 或 gbk)
    sep=',',                    # 分隔符
    header=0,                   # 第0行为列名
    index_col=0,                # 指定列为行索引
    usecols=['name', 'age'],    # 只读取指定列
    nrows=100,                  # 只读前100行
    na_values=['无', '未知']    # 将特定值视为缺失值
)

# 写入 CSV
df.to_csv('output.csv', index=False, encoding='utf-8')

读取 Excel 文件(需安装 openpyxl)

# pip install openpyxl
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
df = pd.read_excel('data.xlsx', sheet_name=None)   # 读取所有 sheet,返回字典

# 写入 Excel
df.to_excel('output.xlsx', sheet_name='result', index=False)

读取 JSON 文件

df = pd.read_json('data.json', orient='records')   # 记录式 JSON
df.to_json('output.json', orient='records', force_ascii=False)

4.2.3 数据查看:head()info()describe()

# 预览前/后几行
df.head(10)      # 前10行
df.tail(5)       # 后5行

# 基本信息(行数、列数、缺失值、数据类型)
df.info()

# 数值列统计描述(均值、标准差、分位数等)
df.describe()

# 对分类列统计
df['category'].value_counts()

# 其他常用属性
df.shape         # (行数, 列数)
df.columns       # 列名列表
df.index         # 行索引

4.2.4 数据清洗:处理缺失值、重复值、异常值

缺失值处理

# 检测缺失值
df.isnull().sum()          # 每列缺失值数量

# 删除缺失值
df.dropna()                # 删除任何含缺失的行
df.dropna(subset=['age'])  # 指定列有缺失才删除
df.dropna(how='all')       # 全行缺失才删除

# 填充缺失值
df.fillna(0)               # 用0填充
df.fillna({'age': df['age'].mean(), 'city': '未知'})
df['age'].fillna(df['age'].median(), inplace=True)

# 向前/向后填充
df.fillna(method='ffill')  # 用前一个值填充
df.fillna(method='bfill')  # 用后一个值填充

重复值处理

# 检测重复行
df.duplicated().sum()

# 删除重复行(保留第一次出现)
df.drop_duplicates()
df.drop_duplicates(subset=['name'])   # 基于指定列
df.drop_duplicates(keep='last')       # 保留最后一条

异常值处理

# 基于四分位数(IQR)
Q1 = df['age'].quantile(0.25)
Q3 = df['age'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
df_normal = df[(df['age'] >= lower) & (df['age'] <= upper)]

# 基于标准差(适合正态分布)
mean = df['score'].mean()
std = df['score'].std()
df_normal = df[(df['score'] >= mean - 3*std) & (df['score'] <= mean + 3*std)]

# 手动替换/删除
df.loc[df['age'] > 100, 'age'] = df['age'].mean()
df = df[df['score'] >= 0]

4.2.5 数据筛选与条件过滤:loc / iloc / 布尔索引

iloc(按整数位置筛选,左闭右开)

df.iloc[0]          # 第一行
df.iloc[1:4, 2:5]   # 行1-3,列2-4
df.iloc[:, [0,2]]   # 所有行,第0和2列

loc(按标签/条件筛选,包含结束标签)

df.loc[0]                 # 索引为0的行
df.loc[0:3, 'name':'age'] # 索引0-3,列name到age
df.loc[df['age'] > 25]    # 条件筛选
df.loc[df['age'] > 25, 'name']

布尔索引(直接条件)

# 单条件
df[df['age'] > 25]

# 多条件(& 且,| 或,~ 非,注意括号)
df[(df['age'] > 25) & (df['city'] == '北京')]
df[df['city'].isin(['北京', '上海'])]
df[~df['status'].isin(['deleted'])]

# 字符串方法
df[df['name'].str.startswith('张')]
df[df['email'].str.contains('@example.com')]

loc 与 iloc 对比

方法 筛选依据 切片规则 适用场景
iloc 整数位置 左闭右开 已知行列位置
loc 标签或条件 左闭右闭 已知标签或条件筛选

4.2.6 分组聚合:groupby() + agg()

# 单列分组,单聚合
df.groupby('city')['age'].mean()

# 多列分组
df.groupby(['city', 'gender'])['score'].mean()

# 多个聚合函数
df.groupby('city')['age'].agg(['mean', 'std', 'count'])

# 对不同列不同聚合
df.groupby('city').agg({
    'age': 'mean',
    'score': ['min', 'max'],
    'name': 'count'
})

# 命名聚合(推荐)
result = df.groupby('city').agg(
    avg_age=('age', 'mean'),
    max_score=('score', 'max'),
    total=('name', 'count')
)

# 分组筛选(filter)
df.groupby('class').filter(lambda x: x['score'].mean() > 85)

# 重置索引
df.groupby('city')['age'].mean().reset_index()

4.2.7 数据合并:concatmerge(类似 SQL 的 join)

concat(拼接)

# 垂直拼接(行追加)
df1 = pd.DataFrame({'A': [1,2], 'B': [3,4]})
df2 = pd.DataFrame({'A': [5,6], 'B': [7,8]})
pd.concat([df1, df2], axis=0, ignore_index=True)

# 水平拼接(列合并)
df3 = pd.DataFrame({'C': [9,10]})
pd.concat([df1, df3], axis=1)

merge(关联,类似 SQL join)

left = pd.DataFrame({'id': [1,2,3], 'name': ['A','B','C']})
right = pd.DataFrame({'id': [1,2,4], 'score': [85,92,78]})

# 内连接(默认)
pd.merge(left, right, on='id', how='inner')

# 左连接、右连接、外连接
pd.merge(left, right, on='id', how='left')
pd.merge(left, right, on='id', how='right')
pd.merge(left, right, on='id', how='outer')

# 不同列名连接
pd.merge(left, right, left_on='id', right_on='user_id')

# 多列连接
pd.merge(df1, df2, on=['key1', 'key2'])

# 处理重复列名
pd.merge(df1, df2, on='id', suffixes=('_left', '_right'))

4.2.8 透视表:pivot_table

# 基础透视表
pivot = pd.pivot_table(
    df,
    values='销售额',
    index='城市',      # 行分组
    columns='产品',    # 列分组
    aggfunc='sum'      # 聚合函数
)

# 多值、多聚合
pivot2 = pd.pivot_table(
    df,
    values=['销售额', '数量'],
    index='城市',
    columns='产品',
    aggfunc={'销售额': 'sum', '数量': 'mean'}
)

# 添加边际(总计)
pivot3 = pd.pivot_table(
    df,
    values='销售额',
    index='城市',
    columns='产品',
    aggfunc='sum',
    margins=True,
    margins_name='总计'
)

# 多级行索引
pivot4 = pd.pivot_table(
    df,
    values='销售额',
    index=['城市', '产品'],
    aggfunc='sum'
)

# 重置透视表索引
pivot4.reset_index()

📚 学习资料(Obsidian 可直接收藏)


🎯 学习建议(2 天计划)

  1. 第 1 天:掌握 Series/DataFrame 创建、数据读取、数据查看(head/info/describe)、数据清洗(缺失值、重复值、异常值)。
  2. 第 2 天:学习数据筛选(loc/iloc/布尔索引)、分组聚合(groupby + agg)、数据合并(concat/merge)、透视表(pivot_table)。

✅ 核心要点总结

  1. Series:一维带标签数组;DataFrame:二维表格,类似 Excel。
  2. 数据读取read_csvread_excelread_json,注意编码和参数。
  3. 数据清洗dropna/fillna 处理缺失值;drop_duplicates 去重;条件过滤处理异常值。
  4. 筛选loc(标签/条件)、iloc(位置)、布尔索引(df[条件])。
  5. 分组聚合groupby() + agg() 或 aggregate(),可自定义函数。
  6. 合并concat 拼接(行/列);merge 按键连接(内/左/右/外)。
  7. 透视表pivot_table 实现数据透视,支持多级索引和边际统计。

练习题(自测)

  1. 读取一个 CSV 文件(可自己创建),查看其基本信息,处理缺失值(填充均值)并删除重复行。
  2. 筛选出某列大于某个阈值的所有行,并只保留指定的几列。
  3. 使用 groupby 计算不同类别下的平均值、最大值和计数。
  4. 将两个 DataFrame 按照某列进行左连接,并处理列名冲突。
  5. 创建一个销售数据表,使用 pivot_table 统计每个销售员、每个产品的总销售额和平均数量。

建议使用 Jupyter Notebook 或 VS Code 逐行运行示例,观察输出结果。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐