Pandas 数据选择与切片

数据选择和切片是数据分析中最频繁的操作。Pandas 提供了多种灵活的方式——基于标签、位置、条件——让你能精准提取需要的行和列。掌握这些技巧,可以极大提升数据处理的效率。

📌 准备示例数据

先创建一个 DataFrame,用于后续演示:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六', '陈七'],
    '年龄': [28, 35, 42, 29, 31],
    '工资': [8000, 12000, 15000, 9500, 11000],
    '部门': ['技术', '销售', '技术', '管理', '销售'],
    '入职年份': [2020, 2018, 2015, 2021, 2019]
})
df.index = ['A', 'B', 'C', 'D', 'E']   # 自定义行索引
print(df)

📋 列选择

单列选择
df['姓名']        # 返回 Series
df.姓名           # 点号访问(列名需为有效标识符)
多列选择
df[['姓名', '工资']]   # 返回 DataFrame

📏 行选择与切片

基于位置切片
df[0:3]          # 前3行(类似列表切片,不包含结束)
df[1:4]          # 第2到4行
基于标签切片(需排序)
df['A':'C']      # 包含结束标签 'C'

🎯 精准索引:.loc[].iloc[]

这是 Pandas 中最推荐的索引方式,清晰明确。

方法 基于 示例 说明
.loc[] 标签 df.loc['A']
df.loc['A':'C']
df.loc['A', '姓名']
行索引和列名都使用标签。切片包含两端。
.iloc[] 整数位置 df.iloc[0]
df.iloc[0:3]
df.iloc[0, 1]
基于从0开始的位置索引。切片不包含结束。
# .loc[] 示例
print(df.loc['B'])                # 选择行 'B'(返回 Series)
print(df.loc['B':'D', '姓名':'工资'])  # 行标签 B 到 D,列名 姓名 到 工资
print(df.loc[['A','C','E'], ['姓名','部门']])  # 选择指定行和列

# .iloc[] 示例
print(df.iloc[0])                 # 第一行
print(df.iloc[1:4, 0:3])          # 第2~4行,第1~3列
print(df.iloc[[0,2,4], [0,2]])    # 指定行和列的位置

🔍 布尔索引(条件筛选)

根据条件筛选行,是数据分析中最常用的操作之一。

# 筛选年龄大于30的员工
df[df['年龄'] > 30]

# 多条件筛选:年龄大于30且部门为销售
df[(df['年龄'] > 30) & (df['部门'] == '销售')]

# 或条件:部门为技术或管理
df[(df['部门'] == '技术') | (df['部门'] == '管理')]

# 取反:年龄不大于30
df[~(df['年龄'] > 30)]

🔢 其他常用筛选方法

isin() 成员判断
between() 区间判断
.str.contains() 字符串包含
.isna() / .notna() 缺失值
.query() 类SQL查询
# isin():筛选部门为技术或销售
df[df['部门'].isin(['技术', '销售'])]

# between():筛选工资在8000到12000之间
df[df['工资'].between(8000, 12000)]

# str.contains():筛选姓名包含“张”的行
df[df['姓名'].str.contains('张')]

# query():字符串表达式(更简洁)
df.query('年龄 > 30 and 部门 == "销售"')

⚡ 同时选择行和列

结合 .loc[].iloc[] 可以一步到位:

# 选择年龄大于30的员工的姓名和工资
df.loc[df['年龄'] > 30, ['姓名', '工资']]

# 选择前两行的姓名和部门
df.iloc[0:2, [0, 3]]   # 第1、2行,第1、4列

# 使用布尔条件同时选择
df.loc[(df['部门'] == '技术') & (df['工资'] > 10000), ['姓名', '入职年份']]

⚠️ 视图与副本的注意事项

链式赋值警告:尽量避免使用类似 df[df['年龄']>30]['工资'] = 10000 的链式索引进行赋值,因为它可能操作的是视图的副本,不会修改原 DataFrame,并可能引发警告。正确的做法是使用 df.loc[df['年龄']>30, '工资'] = 10000
返回视图还是副本?Pandas 的行为有时不确定,但用 .loc[].iloc[] 做赋值操作是安全的。如果想明确复制,使用 .copy()

📌 总结:选择策略速查

  • 要选列: df['列名']df[['列1','列2']]
  • 要选行(按位置): df.iloc[start:end]
  • 要选行(按标签): df.loc[标签]
  • 要条件筛选行: df[条件]
  • 要同时选行列: df.loc[行条件, 列条件]df.iloc[行位置, 列位置]
最佳实践:尽量使用 .loc[].iloc[] 进行索引,尤其是在赋值时。这会让代码更清晰,并避免潜在的错误。