最近在系统学习pandas库,在看读写文件部分,发现输出csv时一些有特殊意义的字符串无法正常显示,例如双引号、NA、None等。示例代码如下:
import os
os.makedirs(os.path.join('.', 'data'), exist_ok=True)
data_file = os.path.join('.', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 列名
f.write('NA,"NA",\'NA\'\n') # 每行表示一个数据样本
f.write('"4",None,NAN\n')
f.write('4,"NaN",178100\n')
f.write('nan,,140000\n')
file_path = os.path.abspath(data_file)
print(file_path)
import pandas as pd
data = pd.read_csv(data_file)
print(data)
这段代码表示在本目录下创建一个data目录,并在data目录下创建house_tiny.csv文件,写入内容,输出文件的绝对路径,并输出文件。
其中,os.path.join()函数的括号中,'.'表示本目录('..'表示父目录)。
os.makedirs()
函数的exist_ok参数
设置为True
时,如果目标目录已经存在,该函数不会引发错误,而是继续执行。如果设置为False
(默认值),当目标目录已经存在时,会引发一个FileExistsError
异常。with open XXX as XXX: 通过该方式读写的文件不需要f.close,因为这种形式本身会在执行完缩进的所有内容后保存。
abspath()函数输出data_file文件的绝对路径。关于其详细用法可另行查阅。
生成的csv文件如下:
NumRooms,Alley,Price
NA,"NA",'NA'
"4",None,NAN
4,"NaN",178100
nan,,140000
但程序输出结果如下:
D:\Software\VS Code\My code\d2l\data\house_tiny.csv
NumRooms Alley Price
0 NaN NaN 'NA'
1 4.0 NaN NAN
2 4.0 NaN 178100
3 NaN NaN 140000
可以看到,生成的csv文件中原原本本地保留了我们输入的内容,但是在read_csv步骤中,成对的双引号被略去了,NA、None、NaN、nan、空缺值都被替换为了NaN,成对的单引号和NAN则没有影响。在很多时候,这种替换给我们带来了便利,但如果我们就是想输出原本的字符串而非输出NaN,这又该怎么办呢?
实际上,keep_default_na和quoting这两个参数控制了这两个问题。只需将read_csv函数的参数修改这以下即可。
data = pd.read_csv(data_file, keep_default_na=False, quoting=csv.QUOTE_NONE)
在read_csv函数中,默认设置了一些字符串为NaN,以上正是输入了这些默认字符串导致输出为NaN。解决办法是将keep_default_na设置为False(默认为True)。
另外的,有方法说可以通过设置read_csv函数的na_values参数来达到这一点。实操发现,设置na_values只会增加na判定的字符串,而不能覆盖原本的判定列表,示例与运行结果如下:
import pandas as pd
data = pd.read_csv(data_file, na_values=None)
print(data)
data = pd.read_csv(data_file, na_values=[])
print(data)
data = pd.read_csv(data_file, na_values=['NAN'])
print(data)
D:\Software\VS Code\My code\d2l\data\house_tiny.csv
NumRooms Alley Price
0 NaN NaN 'NA'
1 4.0 NaN NAN
2 4.0 NaN 178100
3 NaN NaN 140000
NumRooms Alley Price
0 NaN NaN 'NA'
1 4.0 NaN NAN
2 4.0 NaN 178100
3 NaN NaN 140000
NumRooms Alley Price
0 NaN NaN 'NA'
1 4.0 NaN NaN
2 4.0 NaN 178100
3 NaN NaN 140000
read_csv函数中,quotechar参数
用于指定在输出的CSV文件中哪些字符应该被引用。默认情况下,quotechar
是双引号("),即quotechar = ' " '。然而,如果你希望在输出的CSV文件中不使用任何引用字符,则可以通过设置quoting
参数为csv.QUOTE_NONE
来实现这一点。
另外的,你也可以将quotechar设置成别的符号(单引号、双引号、空格、2、N等等很多字符都可以,但必须是单字符,且相当不建议用字母与数字等容易产生干扰的字符),识别到成对的quotechar时程序会将其消去。示例和运行结果如下:
data = pd.read_csv(data_file,quotechar="'")
print(data)
D:\Software\VS Code\My code\d2l\data\house_tiny.csv
NumRooms Alley Price
0 NaN "NA" NaN
1 "4" NaN NAN
2 4 "NaN" 178100
3 NaN NaN 140000
最后,quoting参数需要导入csv库,而我们需要的仅仅是一个QUOTE_NONE参数,这无疑是不值当的。是否有不导入csv的方法?若数据中一部分default_na字符需要被转换,一部分不需要;甚至是同一字符串在一些行列里需要转换,在另一些里不转换,这种情况又有什么好的处理方法?欢迎各位大神在讨论区指点。
参考文章:pandas中na_values与keep_default_na - 宋讼颂 - 博客园 (cnblogs.com)