如何为`csv.reader`指定空值字符?

brgchamk  于 7个月前  发布在  其他
关注(0)|答案(2)|浏览(73)

我想读取“csv”文件,\u0000为null,\u0001为行结束符,u0002为null。对于后两个有两个参数:

csv.reader(csvfile, lineterminator='\u0001', delimiter='\u0002')

字符串
是否有空值字符的参数?

oknwwptz

oknwwptz1#

您可以使用pandas.read_csv,因为它支持替代字符作为行结束符,并将'\u0000'转换为np.nan,以便您可以使用DataFrame.replace方法轻松地将其替换为None
请注意,您必须事先知道CSV中的列数,以便将一系列数字作为列名传递给它。然后您可以将Rename转换为numpy数组进行迭代:

import io
import numpy as np
import pandas as pd

csv = io.StringIO('\u0000\u0002a\u0002b\u0001\u0000\u0002c\u0002d\u0001')
for a, b, c in pd.read_csv(
        csv, names=range(3), lineterminator='\u0001', delimiter='\u0002'
    ).replace(np.nan, None).to_numpy():
    print(a, b, c)

字符串
这将产生:

None a b
None c d


你也可以使用tolist方法将numpy数组转换为列表的列表:

print(pd.read_csv(
    csv, names=range(3), lineterminator='\u0001', delimiter='\u0002'
).replace(np.nan, None).to_numpy().tolist())


其输出:

[[None, 'a', 'b'], [None, 'c', 'd']]

zpf6vheq

zpf6vheq2#

我认为在将文件传递给CSV阅读器之前需要对它进行预处理,因为CSV阅读器无法单独满足您的两个期望:

  • 无“空”值
  • lineterminator仅适用于writer,来自docs^1:

读取器被硬编码为将'\r''\n'识别为行尾,并忽略 * linetimator *。这种行为将来可能会改变。
由于您的两个字符对CSV阅读器没有意义,我认为您需要对文件进行预处理,并将它们替换为有意义的值。
给定一个输入文件,如:

with open("input.csv", "w") as f:
    f.write("\u0000\u0002val_1\u0002val_2\u0001")
    f.write("\u0000\u0002val_3\u0002val_4\u0001")
hexdump -C input.csv 
00000000  00 02 76 61 6c 5f 31 02  76 61 6c 5f 32 01 00 02  |..val_1.val_2...|
00000010  76 61 6c 5f 33 02 76 61  6c 5f 34 01              |val_3.val_4.|
0000001c

可能会像这样预处理文件:

with (
    open("input.csv") as f_in,
    open("fixed.csv", "w") as f_out,
):
    txt = f_in.read()
    txt = txt.replace("\u0001", "\n")  # add line endings that CSV reader recognizes
    txt = txt.replace("\u0000", "")  # go ahead and clear out \u0000
    f_out.write(txt)


然后像这样阅读CSV:

import csv

with open("fixed.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f, delimiter="\u0002")
    for row in reader:
        print(row)


来获取类似于以下内容的行变量:

['', 'val_1', 'val_2']
['', 'val_3', 'val_4']


我选择清除\u0000值,因为CSV读取器不会将空解释为None;写入器会将None解释为空。尽管如此,CSV文件中的空字段是正常的。
如果你不想在预处理中替换\u0001,那么内部的行将看起来像这样:

['\x00', 'val_1', 'val_2']
['\x00', 'val_3', 'val_4']


您可以根据需要处理'\x00'

相关问题