Python使用to_csv进行大浮动

Python使用to_csv进行大浮动,python,pandas,precision,Python,Pandas,Precision,我对用Python将大量数字保存到csv有一个很好的理解。这些数字是毫秒历元时间戳,我无法转换或截断,必须以这种格式保存。由于带有毫秒时间戳的列也包含一些NaN值,pandas会自动将它们转换为浮点(请参见“支持整数NA”下的Gotchas) 我似乎无法避免这种行为,所以我的问题是,在使用df.to_csv时,如何将这些数字保存为整数值,即没有小数点或尾随零?我在同一数据帧中有具有不同浮点精度的数字的列,我不想丢失其中的信息。使用float_格式meter in to_csv似乎对我的数据帧中的

我对用Python将大量数字保存到csv有一个很好的理解。这些数字是毫秒历元时间戳,我无法转换或截断,必须以这种格式保存。由于带有毫秒时间戳的列也包含一些NaN值,pandas会自动将它们转换为浮点(请参见“支持整数NA”下的Gotchas)

我似乎无法避免这种行为,所以我的问题是,在使用df.to_csv时,如何将这些数字保存为整数值,即没有小数点或尾随零?我在同一数据帧中有具有不同浮点精度的数字的列,我不想丢失其中的信息。使用
float_格式meter in to_csv似乎对我的数据帧中的所有浮点列应用相同的格式

例如:

>>> df = pd.DataFrame({'a':[1.25, 2.54], 'b':[1424380449437, 1425510731187]})
>>> df['b'].dtype
Out[1]: dtype('int64')
>>> df.loc[2] = np.NaN
>>> df
Out[1]: 
       a             b
0   1.25  1.424380e+12
1   2.54  1.425511e+12
2    NaN           NaN
>>> df['b'].dtype
dtype('float64')
>>> df.to_csv('test.csv')
>>> with open ('test.csv') as f:
...     for line in f:
...         print(line)
,a,b
0,1.25,1.42438044944e+12
1,2.54,1.42551073119e+12
2,,
如您所见,我丢失了历元时间戳的最后两位数字的精度。

虽然没有参数来更改单个列的格式,但确实有。这有点麻烦,对于非常大的数据帧可能是个问题,但您可以使用它生成格式正确的字符串,然后将该字符串写入文件(如本文中对类似问题的建议)。
to_string
格式化程序
参数以函数字典为例格式化各个列。在您的情况下,您可以为
“b”
列编写自己的自定义格式化程序,保留其他列的默认值。此格式化程序可能看起来有点像:

def printInt(b):
如果pd.isnull(b):
返回“NaN”
其他:
返回“{:d}”。格式(int(b))
现在,您可以使用它生成字符串:

df.to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”)
其中:

'      a             b\n0  1.25 1424380449437\n1  2.54 1425510731187\n2   NaN           NaN'
您可以看到,仍然存在一个问题,即这不是逗号分隔的,而且
to_string
实际上没有设置自定义分隔符的参数,但这可以通过正则表达式轻松解决:

重新导入
关于sub(“[\t]+(NaN)?”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”))
给出:

”,a,b\n0,1.251424380449437\n1,2.541425510731187\n2,
现在可以将其写入文件:

打开(“/tmp/test.csv”,“w”)作为f:
打印(re.sub(“[\t]+(NaN)”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”),
文件=f)
这会产生你想要的结果:

,a,b
0,1.25,1424380449437  
1,2.54,1425510731187  
2.

如果要在csv文件中保留
NaN
,只需更改正则表达式:

打开(“/tmp/test.csv”,“w”)作为f:
打印(re.sub(“[\t]+”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”),
文件=f)
将提供:

,a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,楠,楠

如果您的数据帧以前包含带空格的字符串,则可靠的解决方案就不那么容易了。您可以在每个值前面插入另一个字符,这表示下一个条目的开始。如果所有字符串中只有一个空格,您可以使用另一个空格作为示例。这会将代码更改为:

将熊猫作为pd导入
将numpy作为np导入
进口稀土
df=pd.DataFrame({'aaa':[1.25,2.54],'b':[1424380449437,1425510731187]})
df.loc[2]=np.NaN
def printInt(b):
如果pd.isnull(b):
返回“NaN”
其他:
返回“{:d}”。格式(int(b))
def打印浮动(a):
如果pd.isnull(a):
返回“NaN”
其他:
返回“{}”。格式(a)
以open(“/tmp/test.csv”,“w”)作为f:
打印(re.sub(“[\t][\t]+”,“,”,
to_字符串(格式化程序={“a”:printFloat,“b”:printInt},
na_rep=“NaN”,col_space=2)),
文件=f)
这将使:

,a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,楠,楠
虽然没有参数来更改单个列的格式,但有。这有点麻烦,对于非常大的数据帧可能会有问题,但您可以使用它生成格式正确的字符串,然后将该字符串写入文件(如本节中对类似问题的建议).to_string的
格式化程序
参数以函数字典为例格式化各个列。在您的情况下,您可以为
“b”
列编写自己的自定义格式化程序,保留其他列的默认值。此格式化程序可能类似于:

def printInt(b):
如果pd.isnull(b):
返回“NaN”
其他:
返回“{:d}”。格式(int(b))
现在,您可以使用它生成字符串:

df.to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”) 其中:

'      a             b\n0  1.25 1424380449437\n1  2.54 1425510731187\n2   NaN           NaN'
您可以看到,仍然存在一个问题,即这不是逗号分隔的,而且
to_string
实际上没有设置自定义分隔符的参数,但这可以通过正则表达式轻松解决:

重新导入
关于sub(“[\t]+(NaN)?”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”))
给出:

”,a,b\n0,1.251424380449437\n1,2.541425510731187\n2,
现在可以将其写入文件:

打开(“/tmp/test.csv”,“w”)作为f:
打印(re.sub(“[\t]+(NaN)”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”),
文件=f)
这会产生你想要的结果:

,a,b
0,1.25,1424380449437  
1,2.54,1425510731187  
2.

如果要在csv文件中保留
NaN
,只需更改正则表达式:

打开(“/tmp/test.csv”,“w”)作为f:
打印(re.sub(“[\t]+”,“,”,
to_字符串(格式化程序={“b”:printInt},na_rep=“NaN”),
文件=f)
将提供:

,a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,楠,楠

如果您的数据帧不正确