
本教程旨在解决大型csv文件中常见的列数不一致和字符编码问题。我们将使用python的`csv`模块,介绍两种有效策略:首先,精确识别并报告每条列数不符的行及其详细信息;其次,针对海量数据,提供一种将连续异常行聚合成范围进行报告的方法。通过这些技术,用户能够高效地定位并理解数据质量问题,为后续的数据清洗和导入工作奠定基础,同时避免常见的`unicodedecodeerror`。
在数据处理和导入(例如将Excel数据导入Teradata等数据库)过程中,CSV文件因其简洁性而被广泛使用。然而,原始CSV数据往往存在各种“脏”数据问题,尤其是在手动输入或缺乏严格数据验证的场景下。其中最常见的挑战包括:
对于包含数十万行、数十甚至上百列的大型CSV文件,手动检查和修复是不可行的。本教程将展示如何利用Python及其强大的csv模块,高效地识别并报告这些数据质量问题。
处理列数不一致问题的第一步是准确识别哪些行存在问题。相比于简单地统计逗号数量,使用Python内置的csv模块是更健壮的方法,因为它能够正确处理包含逗号的引用字段以及嵌入的换行符。
以下代码演示了如何生成一个报告,列出所有列数不符合预期(例如,期望66列)的行及其对应的实际列数。
立即学习“Python免费学习笔记(深入)”;
import csv
# 设定期望的列数,根据实际情况修改
EXPECTED_COLS = 66
INPUT_FILE = 'Data.csv'
OUTPUT_FILE_FLAT = 'output_anomalous_rows.csv'
def report_single_anomalies(input_csv_path, output_report_path, expected_columns):
"""
识别并报告CSV文件中列数不一致的单个行。
Args:
input_csv_path (str): 输入CSV文件的路径。
output_report_path (str): 输出报告CSV文件的路径。
expected_columns (int): CSV文件期望的列数。
"""
print(f"开始分析文件: {input_csv_path}")
print(f"期望列数: {expected_columns}")
try:
with open(output_report_path, 'w', newline='', encoding='utf-8') as f_out:
writer = csv.writer(f_out)
writer.writerow(["行号", "实际列数"]) # 写入报告头
# 推荐使用 'utf-8' 编码,如果遇到 UnicodeDecodeError,可尝试 'latin-1' 或 'gbk'
with open(input_csv_path, 'r', newline='', encoding='utf-8') as f_in:
reader = csv.reader(f_in)
# 跳过CSV文件的标题行(如果存在)
try:
header = next(reader)
# 如果需要,可以在这里检查标题行的列数
print(f"已跳过标题行: {header}")
except StopIteration:
print("文件为空或不含数据。")
return
# 使用enumerate从1开始计数,对应文件中的行号
for i, row in enumerate(reader, start=1):
actual_cols = len(row)
if actual_cols != expected_columns:
writer.writerow([i, actual_cols])
print(f"发现异常行 - 行号: {i}, 实际列数: {actual_cols}")
print(f"异常行报告已生成至: {output_report_path}")
except FileNotFoundError:
print(f"错误:文件 '{input_csv_path}' 未找到。")
except UnicodeDecodeError as e:
print(f"字符编码错误:{e}。请尝试更改文件编码参数,例如 'latin-1' 或 'gbk'。")
except Exception as e:
print(f"发生未知错误:{e}")
# 调用函数进行分析
report_single_anomalies(INPUT_FILE, OUTPUT_FILE_FLAT, EXPECTED_COLS)对于拥有数十万行甚至更多数据的大型CSV文件,如果异常行非常多,生成一个包含每一条异常行的报告可能会非常庞大且难以阅读。在这种情况下,将连续的、具有相同异常列数的行聚合成一个范围进行报告,会更加高效和实用。
import csv
# 设定期望的列数,根据实际情况修改
EXPECTED_COLS = 66
INPUT_FILE = 'Data.csv'
OUTPUT_FILE_RANGES = 'output_anomalous_ranges.csv'
def write_report_row(writer, cols_ct, row_start, row_end):
"""
将异常行范围写入报告文件。
如果起始行和结束行相同,则只写入起始行。
"""
if row_start == row_end:
writer.writerow([cols_ct, row_start, ""]) # 单行异常,结束行留空
else:
writer.writerow([cols_ct, row_start, row_end])
def report_anomalous_ranges(input_csv_path, output_report_path, expected_columns):
"""
识别并报告CSV文件中列数不一致的行范围。
Args:
input_csv_path (str): 输入CSV文件的路径。
output_report_path (str): 输出报告CSV文件的路径。
expected_columns (int): CSV文件期望的列数。
"""
print(f"开始分析文件 (范围报告): {input_csv_path}")
print(f"期望列数: {expected_columns}")
# 定义追踪状态常量
NO_TRACK = -1
try:
with open(output_report_path, 'w', newline='', encoding='utf-8') as f_out:
writer = csv.writer(f_out)
writer.writerow(["实际列数", "起始行", "结束行"]) # 写入报告头
with open(input_csv_path, 'r', newline='', encoding='utf-8') as f_in:
reader = csv.reader(f_in)
# 处理标题行
try:
header = next(reader)
# 可以在这里根据标题行确定期望列数,或检查其列数
print(f"已跳过标题行: {header}")
except StopIteration:
print("文件为空或不含数据。")
return
# 初始化追踪变量
tracking = False # 是否正在追踪一个异常范围
row_num_start = NO_TRACK # 当前异常范围的起始行号
cols_count_in_range = NO_TRACK # 当前异常范围的列数
last_processed_row_index = 0 # 记录循环中最后处理的行索引 (用于最终flush)
for i, row in enumerate(reader, start=1):
last_processed_row_index = i # 更新最后处理的行索引
current_cols = len(row)
# 如果当前行的列数与当前追踪的列数不同
if current_cols != cols_count_in_range:
# 如果正在追踪一个范围,则结束它并写入报告
if tracking:
write_report_row(writer, cols_count_in_range, row_num_start, i - 1) # i-1 是前一行
# 判断当前行是否为异常行
if current_cols == expected_columns:
# 当前行正常,停止追踪
tracking = False
row_num_start = NO_TRACK
cols_count_in_range = NO_TRACK
else:
# 当前行异常,开始新的追踪
tracking = True
row_num_start = i
cols_count_in_range = current_cols
# 如果当前行的列数与当前追踪的列数相同,则继续追踪,无需操作
# 循环结束后,如果还在追踪一个范围,需要将其写入报告
if tracking:
write_report_row(writer, cols_count_in_range, row_num_start, last_processed_row_index)
print(f"异常行范围报告已生成至: {output_report_path}")
except FileNotFoundError:
print(f"错误:文件 '{input_csv_path}' 未找到。")
except UnicodeDecodeError as e:
print(f"字符编码错误:{e}。请尝试更改文件编码参数,例如 'latin-1' 或 'gbk'。")
except Exception as e:
print(f"发生未知错误:{e}")
# 调用函数进行分析
report_anomalous_ranges(INPUT_FILE, OUTPUT_FILE_RANGES, EXPECTED_COLS)通过本教程,您学习了如何使用Python的csv模块高效地识别CSV文件中的数据质量问题,特别是列数不一致和字符编码错误。我们提供了两种报告策略:针对小型数据集的单个异常行报告,以及针对大型数据集的聚合异常行范围报告。这些工具能够帮助您在数据导入前,清晰地了解数据质量状况,为后续的数据清洗和转换工作提供精确的指引,从而确保数据导入的顺利进行和数据质量的可靠性。记住,数据清洗是一个迭代的过程,从识别到修复,每一步都至关重要。
以上就是Python处理CSV文件列数不一致及编码错误的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号