Pandas:输出 Dataframe 到带有整数的csv

cnjp1d6j  于 2023-01-15  发布在  其他
关注(0)|答案(9)|浏览(167)

我有一个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()
13z8s7eq

13z8s7eq1#

这是panda(支持整数NA)中的一个“陷阱”,其中带有NaN的整数列被转换为浮点数。
这种折衷主要是出于内存和性能的考虑,同时也是为了使生成的Series仍然是“numeric”。一种可能性是使用dtype=object数组。

rm5edbpk

rm5edbpk2#

我所寻找的答案与@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')
vd2z7a6w

vd2z7a6w3#

问题是因为你是按行赋值的,但是数据类型是按列分组的,所以数据类型被强制转换成object数据类型,这不是一件好事,你会失去所有的效率。所以一种方法是根据需要将强制转换成float/int数据类型。
正如我们在另一个问题中所回答的,如果您一次性构建框架(或逐列构建),则不需要此步骤

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
smtd7mpg

smtd7mpg4#

如果您想保留导出的csv中的NaN信息,请执行以下操作:在这种情况下,我集中在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

现在,如果您将 Dataframe 导出为csv,列“c”将没有浮点值,NaN信息将保留。

bbuxkriu

bbuxkriu5#

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

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

但这适用于 * 所有 * 浮点列。在Pandas1.1.5上使用您的代码,我的所有列都是float。
输出:

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
sg2wtvxw

sg2wtvxw6#

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

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

liwlm1x97#

您可以使用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})
jq6vz3qz

jq6vz3qz8#

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

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

ua4mk5z49#

这里还有另一个解决方案:

df['IntColumnWithNAValues'].fillna(0, inplace=True)

df['IntColumnWithNAValues'] = df['IntColumnWithNAValues'].astype(int)

df['IntColumnWithNAValues'].replace(0, '', inplace=True)

.csv文件不区分NA或''(空字符串),因为它是一个文本文件,所以您可以在将非空值转换为int时保留丢失的字段。
您可以对所需的每个列执行此操作;如果您有很多列,这可能是一个问题。

相关问题