Pandas-数据选择与过滤

在数据处理过程中,我们很少需要对整个数据集进行操作,更多时候是针对特定的行、列或满足条件的子集进行分析,Pandas提供了灵活强大的数据选择与过滤工具,能够根据标签、位置、条件等多种方式精准提取数据。

一、数据选择的核心对象

Pandas中用于数据选择的核心对象是DataFrameSeries,二者的选择逻辑一致但略有差异:

  • DataFrame:二维表格数据,选择结果可以是列、行或子DataFrame
  • Series:一维数组,选择结果是标量或子Series

数据选择主要围绕三个维度展开:

  • 列选择:提取一个或多个列
  • 行选择:提取满足条件的行
  • 元素选择:提取特定位置的单个元素

二、列选择:提取感兴趣的字段

列选择是最基础的操作,可通过列名直接获取所需字段,适用于快速聚焦关键信息。

1. 选择单个列

通过[]运算符或.属性选择单个列,返回Series对象:

import pandas as pd

# 创建示例DataFrame
data = {
    'user_id': [101, 102, 103, 104, 105],
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
    'age': [25, 30, 35, 40, 45],
    'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai'],
    'score': [85, 92, 78, 90, 88]
}
df = pd.DataFrame(data)

# 方法1:使用[]运算符(推荐,适用于所有列名)
age_series = df['age']
print(age_series)

# 方法2:使用.属性(仅适用于列名无空格且不与方法名冲突的情况)
name_series = df.name
print(name_series)

2. 选择多个列

通过传递列名列表选择多个列,返回子DataFrame:

# 选择多个列
user_info = df[['user_id', 'name', 'city']]
print(user_info)

# 调整列顺序(按列表顺序返回)
score_info = df[['score', 'user_id']]
print(score_info)

实用技巧:结合filter()函数按列名规则选择(如包含特定字符串):

# 选择列名包含"id"的列
id_cols = df.filter(like='id')
print(id_cols)

# 选择列名符合正则表达式的列(以"e"结尾)
e_cols = df.filter(regex='e$')
print(e_cols)

三、行选择:按位置或标签提取

行选择需根据行的位置(整数索引)或标签(索引值)进行,核心工具是iloc(位置索引)和loc(标签索引)。

1. 按位置选择:iloc

iloc基于整数位置(从0开始)选择行,语法与Python列表切片一致:

# 选择单行(返回Series)
row_0 = df.iloc[0]
print(row_0)

# 选择多行(返回DataFrame)
rows_1_3 = df.iloc[1:4]  # 选择位置1到3(不包含4)的行
print(rows_1_3)

# 选择不连续的行
rows_0_4 = df.iloc[[0, 4]]
print(rows_0_4)

# 同时选择行和列(行位置, 列位置)
subset = df.iloc[1:3, [0, 2, 4]]  # 行1-2,列0、2、4
print(subset)

2. 按标签选择:loc

loc基于行标签(索引值)选择行,支持标签切片和条件表达式:

# 先设置有意义的索引(如user_id)
df = df.set_index('user_id')
print(df)

# 按标签选择单行
row_102 = df.loc[102]
print(row_102)

# 按标签切片选择多行(包含终点)
rows_102_104 = df.loc[102:104]  # 选择标签102到104的行
print(rows_102_104)

# 按标签和列名同时选择
subset = df.loc[101:103, ['name', 'score']]  # 行101-103,列name和score
print(subset)

注意:若未自定义索引,loc的标签默认与iloc的位置一致(均为0,1,2…),但二者逻辑不同,避免混淆。

四、条件过滤:按逻辑规则提取行

条件过滤是数据分析中最常用的操作之一,通过逻辑表达式筛选满足条件的行,返回子DataFrame。

1. 单条件过滤

# 选择年龄大于30的行
age_over_30 = df[df['age'] > 30]
# 等价于df.loc[df['age'] > 30]
print(age_over_30)

# 选择城市为北京的行
beijing_users = df[df['city'] == 'Beijing']
print(beijing_users)

# 选择分数在80-90之间的行
score_between = df[(df['score'] >= 80) & (df['score'] <= 90)]
print(score_between)

注意:多个条件需用&(且)、|(或)连接,每个条件需用括号包裹,不可使用and/or

2. 多条件组合

# 年龄大于30且城市为上海
cond1 = df['age'] > 30
cond2 = df['city'] == 'Shanghai'
result = df[cond1 & cond2]
print(result)

# 分数大于90或城市为广州
cond3 = df['score'] > 90
cond4 = df['city'] == 'Guangzhou'
result = df[cond3 | cond4]
print(result)

3. 复杂条件:isin()与字符串方法

# 选择城市在指定列表中的行
target_cities = ['Beijing', 'Shanghai']
city_filter = df[df['city'].isin(target_cities)]
print(city_filter)

# 选择名字包含"li"的行(不区分大小写)
name_filter = df[df['name'].str.contains('li', case=False, na=False)]
print(name_filter)

# 选择分数不在前20%的行
top20_threshold = df['score'].quantile(0.8)
not_top20 = df[df['score'] < top20_threshold]
print(not_top20)

五、高级过滤技巧

1. 结合函数过滤

对于复杂条件,可定义函数并通过apply()实现过滤:

# 定义过滤函数:年龄大于平均年龄且分数高于85
def filter_func(row):
    avg_age = df['age'].mean()
    return row['age'] > avg_age and row['score'] > 85

# 应用函数过滤
filtered = df[df.apply(filter_func, axis=1)]
print(filtered)

2. 随机抽样过滤

需要随机选择部分样本时,使用sample()函数:

# 随机选择3行
random_sample = df.sample(3)
print(random_sample)

# 按比例抽样(10%)
frac_sample = df.sample(frac=0.1)
print(frac_sample)

# 按条件分层抽样(如各城市抽取1人)
stratified_sample = df.groupby('city').apply(lambda x: x.sample(1))
print(stratified_sample)

3. 过滤空值与重复值

结合缺失值和重复值处理进行过滤:

# 过滤特定列无缺失值的行
no_missing = df.dropna(subset=['score'])

# 过滤重复行(保留首次出现)
no_duplicate = df.drop_duplicates(subset=['name', 'city'], keep='first')

六、实战案例:多维度数据提取

# 示例:分析北京地区30岁以上用户的高分记录
# 1. 选择相关列
df_subset = df[['name', 'age', 'city', 'score']]

# 2. 应用多条件过滤
cond = (
    (df_subset['city'] == 'Beijing') &
    (df_subset['age'] > 30) &
    (df_subset['score'] > 80)
)
beijing_high_score = df_subset[cond]

# 3. 按分数降序排列
beijing_high_score = beijing_high_score.sort_values('score', ascending=False)

# 4. 提取前2名
top2 = beijing_high_score.iloc[:2]
print("北京地区30岁以上高分用户前2名:")
print(top2)

七、常见问题与注意事项

  1. 链式索引警告:避免df['col'][row]的链式索引,改用df.loc[row, 'col']df.iloc[row, col_idx],防止修改副本而非原数据。

  2. 条件表达式优先级:多个条件需用括号明确优先级,例如(A & B) | C不等同于A & (B | C)

  3. 空值处理:条件过滤时需注意空值(NaN)会被视为False,可通过na=False参数显式处理(如str.contains(na=False))。

  4. 性能优化:对于大规模数据,优先使用向量化条件(如df['age'] > 30)而非apply()函数,前者速度更快。

总结:数据选择的核心原则

  1. 明确目标:根据需求选择合适的工具(列选择用[],位置选择用iloc,标签/条件选择用loc)。
  2. 向量化优先:尽量使用向量化条件表达式,避免循环和apply(),提升处理速度。
  3. 可读性为王:复杂条件可拆分变量,用清晰的变量名提升代码可维护性(如cond1 & cond2优于嵌套表达式)。

That’s all, thanks for reading~~
觉得有用就点个赞、收进收藏夹吧!关注我,获取更多干货~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值