如何将992×992的大型CSV文件转换为指定格式并去除NA列?
解决方案
纯csv模块实现(无需第三方库)
假设你的原始CSV是宽表结构(每行一个样本,每列一个属性),需要去除含NA的列,并将列名与对应值整理到指定表头的结构中,可按以下步骤处理:
基础版本(适合中等大小文件)
import csv # 配置参数 input_file = "large_input.csv" output_file = "formatted_output.csv" # 替换成你需要的输出表头 output_headers = ["样本标识", "属性名称", "属性值"] # 定义NA的判断规则,根据实际情况调整(比如空字符串、"NA"、"NaN"等) def is_na(value): return value.strip() in ("NA", "", "NaN") # 1. 读取原始数据并筛选有效列 with open(input_file, "r", newline="", encoding="utf-8") as infile: reader = csv.reader(infile) raw_headers = next(reader) rows = list(reader) # 过滤掉列名是NA或整列全为NA的列 valid_col_indices = [] valid_headers = [] for idx, header in enumerate(raw_headers): if is_na(header): continue # 检查整列是否无有效数据 all_na = all(is_na(row[idx]) for row in rows) if not all_na: valid_col_indices.append(idx) valid_headers.append(header) # 2. 重新组织数据并写入输出文件 with open(output_file, "w", newline="", encoding="utf-8") as outfile: writer = csv.writer(outfile) writer.writerow(output_headers) for row_idx, row in enumerate(rows): sample_id = row[0] # 假设第一列是样本标识,根据你的数据调整 for col_idx, header in zip(valid_col_indices, valid_headers): value = row[col_idx] if not is_na(value): writer.writerow([sample_id, header, value])
大内存优化版本(逐行处理)
如果担心一次性加载所有数据占用内存,可改为两次遍历文件:第一次确定有效列,第二次直接处理写入:
import csv input_file = "large_input.csv" output_file = "formatted_output.csv" output_headers = ["样本标识", "属性名称", "属性值"] def is_na(value): return value.strip() in ("NA", "", "NaN") # 第一次遍历:标记有有效数据的列 with open(input_file, "r", newline="", encoding="utf-8") as infile: reader = csv.reader(infile) raw_headers = next(reader) col_has_data = [False] * len(raw_headers) for row in reader: for idx, val in enumerate(row): if not is_na(val): col_has_data[idx] = True # 筛选有效列 valid_col_indices = [idx for idx, (header, has_data) in enumerate(zip(raw_headers, col_has_data)) if not is_na(header) and has_data] valid_headers = [raw_headers[idx] for idx in valid_col_indices] # 第二次遍历:处理并写入数据 with open(input_file, "r", newline="", encoding="utf-8") as infile, \ open(output_file, "w", newline="", encoding="utf-8") as outfile: reader = csv.reader(infile) next(reader) # 跳过原始表头 writer = csv.writer(outfile) writer.writerow(output_headers) for row_idx, row in enumerate(reader): sample_id = row[0] for col_idx, header in zip(valid_col_indices, valid_headers): value = row[col_idx] if not is_na(value): writer.writerow([sample_id, header, value])
简化版pandas实现(高效处理)
如果愿意尝试pandas,几行代码就能完成宽表转长表+去NA列的需求,处理大文件更高效:
import pandas as pd # 读取数据时自动跳过全NA的列 df = pd.read_csv("large_input.csv", na_values=["NA", "", "NaN"], dropna="all", axis=1) # 宽表转长表(假设第一列是样本ID) long_df = df.melt(id_vars=df.columns[0], var_name="属性名称", value_name="属性值") # 移除值为NA的行 long_df = long_df.dropna(subset=["属性值"]) # 写入指定表头的输出文件 long_df.to_csv("formatted_output.csv", header=["样本标识", "属性名称", "属性值"], index=False)
关键调整点
- 若没有单独的样本标识列,可将
sample_id改为行号(比如row_idx + 1) - 修改
is_na函数的判断规则,匹配你文件中NA的实际形式 - 若输出表头不是三列,直接调整
output_headers和写入时的行内容即可
内容的提问来源于stack exchange,提问作者Babbi
相关产品推荐
相关产品推荐

