Pandas读取BX数据集CSV出现隐藏字符导致KeyError问题求助
我太懂这种明明CSV里看着正常,读进Python就出问题的糟心情况了!你遇到的核心问题是编码不匹配加上CSV解析参数没设对,导致读取时引入了隐藏字符,再加上ISBN本身的脏数据(比如空格、特殊符号、字母O和数字0搞混),才触发了KeyError。下面给你一套完整的解决办法:
第一步:修正文件读取的编码和解析参数
你提到BX-Books是ANSI编码(Windows下的ANSI本质是cp1252,而非latin-1,这俩的字符集差异会导致隐藏乱码),BX-Book-Ratings是UTF-8,且所有值都被双引号包裹,所以要明确指定这些参数让pandas正确解析:
import pandas as pd import csv # 读取BX-Books.csv(ANSI编码=cp1252) Books = pd.read_csv( r"C:\Users\Yosafat VS\PycharmProjects\Recomendation_KNN\Data\BX-Books.csv", sep=';', error_bad_lines=False, encoding="cp1252", # 替换latin-1为cp1252,适配Windows ANSI quotechar='"', # 指定字段的包裹引号 quoting=csv.QUOTE_ALL # 告知pandas所有字段都被引号包裹,避免解析错误 ) # 读取BX-Book-Ratings.csv(UTF-8编码) Ratings = pd.read_csv( r"C:\Users\Yosafat VS\PycharmProjects\Recomendation_KNN\Data\BX-Book-Ratings.csv", sep=';', error_bad_lines=False, encoding="utf-8", quotechar='"', quoting=csv.QUOTE_ALL )
第二步:清理ISBN列的脏数据和隐藏字符
即使读取正确,BX数据集的ISBN经常会有各种脏数据(比如开头的空格、*/+/§等特殊符号、把数字0写成字母O),我们写个清理函数统一处理:
def clean_isbn(isbn): # 先转换为字符串,避免非字符串类型的异常 isbn_str = str(isbn).strip() # 去除前后的特殊字符(空格、*、+、`、§都在你的错误示例里出现过) isbn_str = isbn_str.strip(' *+`§') # 清除中间的空格和特殊符号 isbn_str = isbn_str.replace(' ', '').replace('*', '').replace('+', '') # 把常见的输入错误:字母O替换成数字0 isbn_str = isbn_str.replace('O', '0') # ISBN最后一位允许是大写X,统一转为大写 isbn_str = isbn_str.upper() # 过滤掉全0、全X这类无效ISBN invalid_isbns = {'00000000', '000000000', 'XXXXXXXXXX', 'X000000000'} if isbn_str in invalid_isbns: return None return isbn_str # 把清理函数应用到两个数据集的ISBN列 Books['ISBN'] = Books['ISBN'].apply(clean_isbn) Ratings['ISBN'] = Ratings['ISBN'].apply(clean_isbn) # 移除清理后ISBN为None的无效行 Books = Books.dropna(subset=['ISBN']) Ratings = Ratings.dropna(subset=['ISBN'])
第三步:验证并完成映射
现在把Books的索引设置为ISBN,这样后续透视后的Ratings就能正常匹配了:
# 将Books的索引设为ISBN,方便快速查找 Books = Books.set_index('ISBN') # 生成透视表(这里用你原来的逻辑即可) ratings_pivot = Ratings.pivot_table(index='User-ID', columns='ISBN', values='Book-Rating') # 验证匹配是否正常,比如取第一个ISBN测试 sample_isbn = ratings_pivot.columns[0] print("匹配到的书籍信息:") print(Books.loc[sample_isbn])
额外验证:检查共同ISBN数量
你可以运行下面的代码确认两个数据集的有效ISBN交集,确保映射基础是对的:
common_isbns = set(Books.index) & set(Ratings['ISBN']) print(f"两个数据集共有 {len(common_isbns)} 个共同的有效ISBN")
内容的提问来源于stack exchange,提问作者YVS1997
相关产品推荐
相关产品推荐

