儘管pd.to_csv
沒有用於更改各列格式的參數,pd.to_string
的確如此。這有點麻煩,可能是非常大的DataFrames的一個問題,但是您可以使用它來生成格式正確的字符串,然後將該字符串寫入文件(正如此answer中針對類似問題所建議的那樣)。 to_string
的formatters
參數以例如格式化各個列的函數字典爲例。在你的情況下,你可以爲"b"
列編寫自己的自定義格式化程序,並保留其他列的默認值。這種格式看起來有點像這樣:
def printInt(b):
if pd.isnull(b):
return "NaN"
else:
return "{:d}".format(int(b))
現在你可以用它來製作你的字符串:
df.to_string(formatters={"b": printInt}, na_rep="NaN")
這給:
' a b\n0 1.25 1424380449437\n1 2.54 1425510731187\n2 NaN NaN'
你可以看到,仍有問題,這不是逗號分隔和to_string
實際上沒有參數設置自定義分隔符,但這可以很容易地由正則表達式修復:
import re
re.sub("[ \t]+(NaN)?", ",",
df.to_string(formatters={"b": printInt}, na_rep="NaN"))
給出:
',a,b\n0,1.25,1424380449437\n1,2.54,1425510731187\n2,,'
這現在可以寫入文件:
with open("/tmp/test.csv", "w") as f:
print(re.sub("[ \t]+(NaN)?", ",",
df.to_string(formatters={"b": printInt}, na_rep="NaN")),
file=f)
導致你想要的東西:
,a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,,
如果要保持NaN
的在CSV文件,你可以改變的正則表達式:
with open("/tmp/test.csv", "w") as f:
print(re.sub("[ \t]+", ",",
df.to_string(formatters={"b": printInt}, na_rep="NaN")),
file=f)
會給:
,a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,NaN,NaN
如果你的數據幀之前,包含有空格的字符串,一個強大的解決方案並不容易。您可以在每個值的前面插入另一個字符,表示下一個條目的開始。如果所有字符串中只有一個空格,則可以使用另一個空格。這將更改代碼這樣:
import pandas as pd
import numpy as np
import re
df = pd.DataFrame({'a a':[1.25, 2.54], 'b':[1424380449437, 1425510731187]})
df.loc[2] = np.NaN
def printInt(b):
if pd.isnull(b):
return " NaN"
else:
return " {:d}".format(int(b))
def printFloat(a):
if pd.isnull(a):
return " NaN"
else:
return " {}".format(a)
with open("/tmp/test.csv", "w") as f:
print(re.sub("[ \t][ \t]+", ",",
df.to_string(formatters={"a": printFloat, "b": printInt},
na_rep="NaN", col_space=2)),
file=f)
這將使:
,a a,b
0,1.25,1424380449437
1,2.54,1425510731187
2,NaN,NaN
您可以用零替換'nan'值,然後將列轉換爲整數。 'df.b = df.b.fillna(0).astype(int)'或在後面的處理中使用'-1'來標識條目。 –
這是一種可能性,但卻是一種相當笨拙的解決方法。我寧願保留'nan'值,因爲它允許簡單的索引和過濾。此外,我用於'nan'的任何佔位符值可能會自然地出現在Dataframe中。 – Alarik