将 pandas DataFrame 写入 CSV 文件

1100
我在pandas中有一个数据框,我想将其写入CSV文件。
我正在使用以下方法:
df.to_csv('out.csv')

并且出现了以下错误:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u03b1' in position 20: ordinal not in range(128)
  • 有没有简单的方法可以解决这个问题?(例如,我的数据框中有 Unicode 字符)?
  • 是否有一种方法可以使用“to-tab”方法将数据写入制表符分隔文件而不是 CSV(我认为并不存在该方法)?
10个回答

1458

要使用制表符分隔,您可以使用to_csvsep参数:

df.to_csv(file_name, sep='\t')

使用特定的编码(例如“utf-8”)请使用encoding参数:

df.to_csv(file_name, sep='\t', encoding='utf-8')

152
我会在删除时添加 index=False 以去除索引。 - Medhat
42
一开始我很困惑,不知道为什么我能找到七年前已经写过答案的问题的答案。 - Hayden
10
提醒其他使用该功能的人:请以“.csv”结尾命名文件,我不想承认自己忘记这样做了多少次。 - Docconcoct
2
除了被 OP 要求之外,我们使用 to_csv 写入制表符分隔文件的特定原因吗? - DryLabRebel

382

使用to_csv方法将DataFrame对象存储到CSV文件中时,您可能不需要存储每个前置索引

您可以通过向index参数传递False布尔值来避免这种情况。

有点像这样:

df.to_csv(file_name, encoding='utf-8', index=False)

所以,如果你的DataFrame对象类似于:

  Color  Number
0   red     22
1  blue     10

该csv文件将存储:

Color,Number
red,22
blue,10

而不是(当传递了默认值 True 的情况)

,Color,Number
0,red,22
1,blue,10

2
如果需要索引,但也需要标题怎么办?您只需使用 df.rename_axis('index_name') 吗?这不会改变文件本身。 - Zap
如何在文件末尾获取CR /空行?https://dev59.com/xlkS5IYBdhLWcg3w-KpF 不同问题的答案无效。 - Carlos Ferreira

61
要将pandas DataFrame写入CSV文件,您需要使用DataFrame.to_csv函数。此函数提供许多参数,具有合理的默认值,通常需要覆盖这些默认值以适合您的特定用例。例如,您可能想要使用不同的分隔符,更改日期时间格式或在写入时删除索引。 to_csv具有可传递的参数,以满足这些要求。
下面是一个表格,列出了写入CSV文件的一些常见情况,以及您可以用于这些情况的相应参数。

Write to CSV ma dude

脚注
  1. 默认分隔符被假定为逗号(',')。除非您知道需要更改,否则不要更改。
  2. 默认情况下,df的索引被写入为第一列。如果您的DataFrame没有索引(换句话说,df.index是默认的RangeIndex),那么在写入时您将想要设置index=False。换句话说,如果您的数据有索引,您可以(并且应该)使用index=True或完全省略它(因为默认值为True)。
  3. 如果您正在写入字符串数据,设置此参数是明智的,以便其他应用程序知道如何读取您的数据。这也将避免您在保存时可能遇到的任何潜在的UnicodeEncodeError
  4. 如果您要将大型数据框(>100K行)写入磁盘,则建议压缩,因为这将导致输出文件更小。 但是,这意味着写入时间会增加(因此,读取时间也会增加,因为文件需要解压缩)。

39

在 Windows 上导出文件的完整路径示例,如果您的文件有标题:

df.to_csv (r'C:\Users\John\Desktop\export_dataframe.csv', index = None, header=True) 

例如,如果您想将文件存储在与脚本相同的目录中,并使用 utf-8编码 制表符分隔符
df.to_csv(r'./export/dftocsv.csv', sep='\t', encoding='utf-8', header='true')

26

如果你在编码为'utf-8'时遇到问题,并且想逐个单元格进行处理,你可以尝试以下方法。

Python 2

(其中,“df”是您的DataFrame对象。)

for column in df.columns:
    for idx in df[column].index:
        x = df.get_value(idx,column)
        try:
            x = unicode(x.encode('utf-8','ignore'),errors ='ignore') if type(x) == unicode else unicode(str(x),errors='ignore')
            df.set_value(idx,column,x)
        except Exception:
            print 'encoding error: {0} {1}'.format(idx,column)
            df.set_value(idx,column,'')
            continue

那么试试这个:

df.to_csv(file_name)

您可以通过以下方式检查列的编码:


for column in df.columns:
    print '{0} {1}'.format(str(type(df[column][0])),str(column))

警告:errors = 'ignore' 将省略字符,例如

IN: unicode('Regenexx\xae',errors='ignore')
OUT: u'Regenexx'

Python 3

for column in df.columns:
    for idx in df[column].index:
        x = df.get_value(idx,column)
        try:
            x = x if type(x) == str else str(x).encode('utf-8','ignore').decode('utf-8','ignore')
            df.set_value(idx,column,x)
        except Exception:
            print('encoding error: {0} {1}'.format(idx,column))
            df.set_value(idx,column,'')
            continue

20
如果以上解决方案对任何人都不起作用,或者CSV文件被搞乱了,只需从该行中删除sep='\t',就像这样:
df.to_csv(file_name, encoding='utf-8')

如果我的脚本运行在服务器上,每次运行都需要创建一个新的 csv 文件并提供路径给服务器,那么如何实现这个过程?创建文件后如何删除它?(先创建->读取->删除?) - viki
不确定,实际上没有做过那样的经验。 - Shahriar Kabir Khan

18

有时即使你指定了UTF-8编码也会遇到这些问题。我建议你在读取文件时指定编码,并在写入文件时使用相同的编码。这可能会解决你的问题。


12

对于这种情况可能不是万能解决方案,但是由于我遇到了与.to_csv相同的错误消息,所以我尝试使用.toCSV('name.csv')并出现了不同的错误消息(“SparseDataFrame' object has no attribute 'toCSV'”),因此问题被通过将数据框转换为密集数据框来解决。

df.to_dense().to_csv("submission.csv", index = False, sep=',', encoding='utf-8')

1
你在第二个错误中出现了问题,看起来你使用了.toCSV而不是.to_csv。你忘记了下划线。 - Kyle C

4

我会避免使用'\t'分隔符,因为这会在再次读取数据集时产生问题。

df.to_csv(file_name, encoding='utf-8')


1

1. errors= 有时很有用

如果一个文件必须具有特定的编码,但现有的数据框中有无法表示的字符,则可以使用errors=来“强制”将数据保存在成本上丢失信息。可以将所有可能作为Python中open()函数参数传递的值传递到此处。

例如,下面的代码将使用ascii编码保存csv文件,其中日语字符将被替换为?

df = pd.DataFrame({'A': ['Shohei Ohtani は一生に一度の選手だ。']})
df.to_csv('data1.csv', encoding='ascii', errors='replace', index=False)

print(pd.read_csv('data1.csv'))

                           A
0  Shohei Ohtani ???????????

2. float_format= 有时很有用

您可以使用float_format=格式化浮点数据类型,这样做有时可以节省大量内存,但代价是失去精度。例如:

df = pd.DataFrame({'A': [*range(1,9,3)]*1000})/3
df.to_csv('data1.csv', index=False)                       # 61,440 bytes on disk
df.to_csv('data2.csv', index=False, float_format='%.2f')  # 20,480 bytes on disk

3. 保存压缩的csv文件

自从pandas 1.0.0版本以来,您可以将一个字典传递给压缩参数,指定压缩方法和存档中的文件名。下面的代码创建了一个名为compressed_data.zip的zip文件,其中包含一个名为data.csv的单个文件。

df.to_csv('compressed_data.zip', index=False, compression={'method': 'zip', 'archive_name': 'data.csv'})
# read the archived file as a csv
pd.read_csv('compressed_data.zip')

您甚至可以将内容添加到现有的存档中;只需传递 mode='a' 参数即可。

df.to_csv('compressed_data.zip', compression={'method': 'zip', 'archive_name': 'data_new.csv'}, mode='a')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接