Python 3.6 pandas筛选DataFrame遇多类报错及空结果求助
搞定Pandas DataFrame筛选的那些坑:从报错到正确出结果
咱们一步步来拆解你遇到的这些问题,逐个解决:
首先解决最紧急的KeyError: 'year'
你重新加载CSV后碰到这个错误,百分百是重新导入的DataFrame里没有叫year的列,大概率是这俩原因:
- CSV里的列名带空格(比如
year或者year),或者大小写不对(比如写成Year了) - 导入CSV时不小心用了
usecols参数过滤掉了这个列
先跑这行代码确认列名:
print(df_student.columns.tolist())
要是看到列名是[' year', 'Grade', 'Mail']这种带空格的,要么改CSV,要么筛选时用带空格的列名;如果是大小写问题,就用对应大小写的列名,比如df_student['Year']。
正确提取单值Series的标量值
你之前用x.values[0]或者x.iat[0]都是对的,但要注意:
- 如果你不确定x/y/z是Series还是标量,先打印类型确认:
print(type(x), type(y), type(z))
- 要是输出是
<class 'int'>或者<class 'str'>,说明它们已经是标量,直接用就行;如果是<class 'pandas.core.series.Series'>,用x.iat[0]提取标量是最稳妥的(比values[0]更符合pandas的最佳实践) - 你碰到的
AttributeError: 'int' object has no attribute 'astype',就是因为此时x已经是int标量了,根本不需要再用astype(int)转换
解决筛选结果为空的问题:类型匹配是关键
你之前改完代码不报错但结果为空,核心是筛选条件的类型和DataFrame列的类型不匹配,或者字符串有隐形差异:
- DataFrame的
year是int64类型,你得确保筛选的year值是int类型(比如x是字符串"2023",要转成int2023,而不是直接用字符串) Grade和Mail是object类型(本质是字符串),要注意有没有空格、大小写差异——比如"Grade 1"和"grade 1"、"abc@mail.com"和" abc@mail.com "都是不匹配的
可以先打印提取后的筛选值和DataFrame的样本值对比:
# 先处理year值 year_val = int(x.iat[0]) if isinstance(x, pd.Series) else int(x) # 处理Grade和Mail grade_val = y.iat[0].strip() if isinstance(y, pd.Series) else y.strip() mail_val = z.iat[0].strip() if isinstance(z, pd.Series) else z.strip() print("筛选值:", year_val, grade_val, mail_val) print("DataFrame样本值:", df_student['year'].iloc[0], df_student['Grade'].iloc[0].strip(), df_student['Mail'].iloc[0].strip())
要是发现大小写差异,就统一转成小写:
df_student['Grade'] = df_student['Grade'].str.strip().str.lower() grade_val = grade_val.lower() df_student['Mail'] = df_student['Mail'].str.strip().str.lower() mail_val = mail_val.lower()
最终的可用筛选代码
结合以上所有步骤,最终的代码应该是这样的(先确保列名正确):
import pandas as pd # 先确认year列存在,避免KeyError assert 'year' in df_student.columns, "DataFrame里找不到year列,请检查列名拼写、空格或大小写!" # 提取并处理筛选值 # 处理year:确保是int类型,匹配df_student['year']的int64 if isinstance(x, pd.Series): year_val = int(x.iat[0]) else: year_val = int(x) # 如果x是字符串标量,转成int # 处理Grade:去除空格、统一小写 if isinstance(y, pd.Series): grade_val = y.iat[0].strip().lower() else: grade_val = y.strip().lower() # 处理Mail:去除空格、统一小写 if isinstance(z, pd.Series): mail_val = z.iat[0].strip().lower() else: mail_val = z.strip().lower() # 统一DataFrame中对应列的格式,避免匹配失败 df_student['Grade'] = df_student['Grade'].str.strip().str.lower() df_student['Mail'] = df_student['Mail'].str.strip().str.lower() # 执行筛选 df_filter1 = df_student.loc[ (df_student['year'] == year_val) & (df_student['Grade'] == grade_val) & (df_student['Mail'] == mail_val) ] # 查看筛选结果 print(f"筛选到{len(df_filter1)}条数据")
内容的提问来源于stack exchange,提问作者Python Learner
相关产品推荐
相关产品推荐

