如何让pandas.read_csv将空字段转为NaN、保留空字符串?
区分CSV中空字段与空字符串(还原BigQuery导出数据)
你完全是对的——在BigQuery导出的CSV里,无引号的空字段和带引号的""确实对应原表的不同值(NULL和空字符串),但pandas默认的read_csv逻辑会把这两种情况都转成NaN,或者都保留为空字符串,确实让人头疼。不过我们可以通过自定义解析逻辑来实现你的需求,下面一步步说:
解决方案:自定义CSV解析逻辑
因为pandas原生没有提供区分这两种情况的参数,我们可以手动解析CSV行,识别每个字段是否被引号包裹,从而区分无引号的空(转NaN)和带引号的空字符串(保留为空)。这里提供一个适配BigQuery导出格式的实现:
import pandas as pd def read_bigquery_csv(file_path): rows = [] with open(file_path, 'r', encoding='utf-8') as f: # 读取表头 header = f.readline().strip().split(',') for line in f: line = line.strip() if not line: continue fields = [] quoted_fields = [] current_field = [] in_quote = False escape_next = False is_quoted = False for idx, char in enumerate(line): # 处理转义字符 if escape_next: current_field.append(char) escape_next = False continue if char == '\\': escape_next = True continue # 处理引号开关 if char == '"': if idx == 0 or line[idx-1] == ',': is_quoted = True in_quote = not in_quote continue # 处理字段分隔符(仅在非引号内生效) if char == ',' and not in_quote: fields.append(''.join(current_field)) quoted_fields.append(is_quoted) current_field = [] is_quoted = False continue current_field.append(char) # 处理最后一个字段 fields.append(''.join(current_field)) quoted_fields.append(is_quoted) # 转换字段:无引号的空转NaN,其他保留原始值 processed_row = [] for field, was_quoted in zip(fields, quoted_fields): if field == '' and not was_quoted: processed_row.append(None) else: processed_row.append(field) rows.append(processed_row) # 转为DataFrame并调整数据类型(按需) df = pd.DataFrame(rows, columns=header) df['val'] = pd.to_numeric(df['val']) return df # 使用示例 df = read_bigquery_csv('your_file.csv') print(df)
运行这段代码后,就能得到你想要的结果:无引号的空字段(第2行的col)转为NaN,带引号的空字符串(第4行的col)保留为空,同时正确解析转义字符(比如第3行的\f\)和带引号的字符串(第5行的"hi")。
关于CSV标准的说明
传统的CSV规范(比如RFC 4180)并没有强制区分无引号空字段和带引号空字符串,不同工具的实现差异很大。但BigQuery在导出CSV时做了明确约定:
- 原表的
NULL值 → 导出为无引号的空字段(比如,2中的第一个空) - 原表的空字符串 → 导出为带双引号的空字符串(比如
"",4中的第一个字段)
所以你的假设完全正确,这两种情况在这个场景下确实代表不同含义。
Github议题的现状
你提到的4年前的社区讨论确实存在,当时很多用户提出了类似的需求,但截至2024年,pandas的read_csv仍然没有原生支持这种区分——因为不同CSV生成工具的格式差异太大,pandas选择了兼容大多数通用场景的默认行为。所以目前还是需要通过自定义解析来处理BigQuery的这种特殊导出格式。
内容的提问来源于stack exchange,提问作者justhalf
相关产品推荐
相关产品推荐

