Python pandas:使用整数将数据帧输出到csv

Posted

技术标签:

【中文标题】Python pandas:使用整数将数据帧输出到csv【英文标题】:Python pandas: output dataframe to csv with integers 【发布时间】:2013-06-10 04:03:50 【问题描述】:

我有一个pandas.DataFrame,我希望将其导出为 CSV 文件。但是,pandas 似乎将某些值写为 float 而不是 int 类型。我找不到如何改变这种行为。

构建数据框:

df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'], dtype=int)
x = pandas.Series([10,10,10], index=['a','b','d'], dtype=int)
y = pandas.Series([1,5,2,3], index=['a','b','c','d'], dtype=int)
z = pandas.Series([1,2,3,4], index=['a','b','c','d'], dtype=int)
df.loc['x']=x; df.loc['y']=y; df.loc['z']=z

查看:

>>> df
    a   b    c   d
x  10  10  NaN  10
y   1   5    2   3
z   1   2    3   4

导出:

>>> df.to_csv('test.csv', sep='\t', na_rep='0', dtype=int)
>>> for l in open('test.csv'): print l.strip('\n')
        a       b       c       d
x       10.0    10.0    0       10.0
y       1       5       2       3
z       1       2       3       4

为什么十位都有一个点零?

当然,我可以将这个函数粘贴到我的管道中以重新转换整个 CSV 文件,但这似乎没有必要:

def lines_as_integer(path):
    handle = open(path)
    yield handle.next()
    for line in handle:
        line = line.split()
        label = line[0]
        values = map(float, line[1:])
        values = map(int, values)
        yield label + '\t' + '\t'.join(map(str,values)) + '\n'
handle = open(path_table_int, 'w')
handle.writelines(lines_as_integer(path_table_float))
handle.close()

【问题讨论】:

你应该import pandas as pd :) @Andy 我为什么要这样做?命名空间是个好主意...直到您将它们全部缩写并且变得不可读。 @AndyHayden 打字时间更长,但绝对更容易阅读。对于遇到代码的新手来说,pd 表示警察局。或者如果他说法语更糟。 这只是一个约定 - 使用它,或者不使用它 - 取决于您的受众可能是谁的期望 - 对于许多 pandas 用户来说,约定是使用 pd,就像在英国,惯例是靠左行驶。除非您必须共用同一段路,否则这不是问题。 我认为这个类比是不够的,因为靠左行驶与靠右行驶是不相容的。但是,对于了解缩写标准的老手来说,使用完整的包名可以正常工作,而相反则不正确(新手对pd 感到困惑)。 【参考方案1】:

我正在寻找的答案与@Jeff 在他的答案中提出的略有不同。功劳归于他。最终解决了我的问题,以供参考:

import pandas
df = pandas.DataFrame(data, columns=['a','b','c','d'], index=['x','y','z'])
df = df.fillna(0)
df = df.astype(int)
df.to_csv('test.csv', sep='\t')

【讨论】:

这可以解决任何浮点数,但您会丢失 NaN 信息。也许用 -9999 或您知道在您的数据集中不是“真实”的某个值填充 NA。 你可以参考我下面的回答来保留 NaN 如何只为一栏做到这一点?我的df 有混合类型、字符串和数字。 如果您的数据是自然数(非负整数),则可以选择使用df.fillna(-1)【参考方案2】:

这是一个"gotcha" in pandas (Support for integer NA),其中带有 NaN 的整数列被转换为浮点数。

这种权衡主要是出于内存和性能方面的原因,而且结果 Series 仍然是“数字”的。一种可能性是改用dtype=object 数组。

【讨论】:

所以如果不重新解析整个文件就无法将它们作为整数获取?如果我使用df.fillna() 怎么样? 在创建xdf 时使用dtype=object(而不是int)。【参考方案3】:

问题在于,由于您是按行分配事物,但 dtypes 是按列分组的,所以事物被强制转换为 object dtype,这不是一件好事,您会失去所有效率。因此,一种方法是根据需要将其转换为 float/int dtype。

正如我们在另一个问题中回答的那样,如果您一次构建所有框架(或逐列构建),则不需要此步骤

In [23]: def convert(x):
   ....:     try:
   ....:         return x.astype(int)
   ....:     except:
   ....:         return x
   ....:     

In [24]: df.apply(convert)
Out[24]: 
    a   b   c   d
x  10  10 NaN  10
y   1   5   2   3
z   1   2   3   4

In [25]: df.apply(convert).dtypes
Out[25]: 
a      int64
b      int64
c    float64
d      int64
dtype: object

In [26]: df.apply(convert).to_csv('test.csv')

In [27]: !cat test.csv
,a,b,c,d
x,10,10,,10
y,1,5,2.0,3
z,1,2,3.0,4

【讨论】:

但是在c 列中有.0s...:s 因为它是一个浮点数!那里别无选择(你可以将float_format='%.0f' 传递给to_csv,但这可能会导致精度下降—— 但是...,如果您使用 dtype=object(例如在 x 和 df 中通过 OP 的构造,我同意这不是最好的方法),那么 2、3 和 10 都是整数...无论如何,几乎总是不值得担心。这似乎就像 OP 努力的转置:s 是的...继续强调使用object dtype 来表示数字是不好的....如果发生这种情况(例如在这种情况下),我们应该设置一个 PerformanceWarning .... 如果他们不遗余力地选择 dtype=object,当然他们应该得到他们得到的(如果他们不这样做,他们会得到一个浮动)。一个更好的解决方案是让 numpy 支持整数数组中的 NaN... ;)【参考方案4】:

如果您想在已导出的 csv 中保留 NaN 信息,请执行以下操作。 P.S:在这种情况下,我专注于“C”列。

df[c] = df[c].fillna('')       #filling Nan with empty string
df[c] = df[c].astype(str)      #convert the column to string 
>>> df
    a   b    c     d
x  10  10         10
y   1   5    2.0   3
z   1   2    3.0   4

df[c] = df[c].str.split('.')   #split the float value into list based on '.'
>>> df
        a   b    c          d
    x  10  10   ['']       10
    y   1   5   ['2','0']   3
    z   1   2   ['3','0']   4

df[c] = df[c].str[0]            #select 1st element from the list
>>> df
    a   b    c   d
x  10  10       10
y   1   5    2   3
z   1   2    3   4

现在,如果您将数据框导出到 csv,“c”列将没有浮点值,并且保留了 NaN 信息。

【讨论】:

这个解决方案很好,但它假设您知道在哪一列中丢失了数据,这种情况很少见。【参考方案5】:

只需将其作为字符串写入 csv:

df.to_csv('test.csv', sep='\t', na_rep='0', dtype=str)

【讨论】:

它根本不起作用。 TypeError: to_csv() 得到了一个意外的关键字参数“dtype” 如果不行,使用astype()转换数据类型【参考方案6】:

您可以使用 astype() 为每一列指定数据类型

例如:

import pandas
df = pandas.DataFrame(data, columns=['a','b','c','d'], index=['x','y','z'])

df = df.astype("a": int, "b": complex, "c" : float, "d" : int)

【讨论】:

【参考方案7】:

您可以将 DataFrame 更改为 Numpy 数组作为解决方法:

 np.savetxt(savepath, np.array(df).astype(np.int), fmt='%i', delimiter = ',', header= 'PassengerId,Survived', comments='')

【讨论】:

【参考方案8】:

最简单的解决方案是在pd.read_csv()中使用float_format

df.to_csv('test.csv', sep='\t', na_rep=0, float_format='%.0f')

但这适用于 所有 浮动列。顺便说一句:在 pandas 1.1.5 上使用您的代码,我的所有列都是浮动的。

输出:

    a   b   c   d
x   10  10  0   10
y   1   5   2   3
z   1   2   3   4

没有float_format

    a   b   c   d
x   10.0    10.0    0    10.0
y    1.0     5.0    2.0   3.0
z    1.0     2.0    3.0   4.0

【讨论】:

以上是关于Python pandas:使用整数将数据帧输出到csv的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历多个 panda 数据帧以在 Python 中获取多个数据帧输出

python:pandas - 如何将前两行 pandas 数据帧组合到数据帧头?

Python 3.x - 使用 for 循环将数据附加到 Pandas 数据帧

在不创建外部文本文件的情况下将终端输出捕获到 pandas 数据帧中

python pandas:仅将数据帧的结构(无行)导出到 SQL

如何将SalesForce数据导入Python Panda数据帧