Pandas-数据选择与过滤
在数据处理过程中,我们很少需要对整个数据集进行操作,更多时候是针对特定的行、列或满足条件的子集进行分析,Pandas提供了灵活强大的数据选择与过滤工具,能够根据标签、位置、条件等多种方式精准提取数据。
一、数据选择的核心对象
Pandas中用于数据选择的核心对象是DataFrame和Series,二者的选择逻辑一致但略有差异:
- 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)
七、常见问题与注意事项
-
链式索引警告:避免
df['col'][row]
的链式索引,改用df.loc[row, 'col']
或df.iloc[row, col_idx]
,防止修改副本而非原数据。 -
条件表达式优先级:多个条件需用括号明确优先级,例如
(A & B) | C
不等同于A & (B | C)
。 -
空值处理:条件过滤时需注意空值(NaN)会被视为
False
,可通过na=False
参数显式处理(如str.contains(na=False)
)。 -
性能优化:对于大规模数据,优先使用向量化条件(如
df['age'] > 30
)而非apply()
函数,前者速度更快。
总结:数据选择的核心原则
- 明确目标:根据需求选择合适的工具(列选择用
[]
,位置选择用iloc
,标签/条件选择用loc
)。- 向量化优先:尽量使用向量化条件表达式,避免循环和
apply()
,提升处理速度。- 可读性为王:复杂条件可拆分变量,用清晰的变量名提升代码可维护性(如
cond1 & cond2
优于嵌套表达式)。
That’s all, thanks for reading~~
觉得有用就点个赞
、收进收藏
夹吧!关注
我,获取更多干货~