2017-09-15 14 views
1

私はを持っています。これはPythonで大量のcsvを保存しています。数値はミリ秒のエポックタイムスタンプです。このスタンプは変換や切り捨てができず、この形式で保存する必要があります。ミリ秒のタイムスタンプを持つ列にはいくつかのNaN値も含まれているので、パンダはそれらを自動的にfloatにキャストします(「整数NAのサポート」のを参照してください)。Pythonパンダto_csvの大きな浮動小数点

私の質問は、 df.to_csvを使用すると、これらの数値を整数値として保存するにはどうしたらいいですか?つまり、小数点や末尾のゼロはありませんか?同じデータフレーム内に異なる浮動小数点数の列があります。 to_csvでfloat_formatパラメータは、私のデータフレーム内のすべてのフロートの列に同じフォーマットを適用するように思わ

例:。

>>> 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,, 

ご覧のとおり、エポックタイムスタンプの最後の2桁の精度が失われました。

+0

潜在的に 'nan'値をゼロに置き換えて、列をintergerに変換することができます。 'df.b = df.b.fillna(0).astype(int)'または '-1'を使って後で処理する際のエントリを識別します。 –

+0

それは可能ですが、かなりぎこちない回避策です。簡単なインデックス作成とフィルタリングが可能なため、「ナノ」値をそのまま使用することをお勧めします。また、「ナノ」に使用するプレースホルダの値は、データフレーム内で自然に発生する可能性があります。 – Alarik

答えて

1

pd.to_csvには、個々の列の形式を変更するパラメータがありませんが、pd.to_stringはあります。少し面倒で、非常に大きなDataFramesでは問題になるかもしれませんが、正しくフォーマットされた文字列を生成し、その文字列をファイルに書き込むことができます(これはanswer同様の質問です)。 to_stringformattersパラメータは、たとえば、個々の列をフォーマットする関数の辞書を取ります。あなたのケースでは、列の独自のカスタムフォーマッタを作成し、他の列の既定値を残すことができます。このフォーマッタは、多少のようになります。

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")) 

ができます:

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,, 

もし

',a,b\n0,1.25,1424380449437\n1,2.54,1425510731187\n2,,' 

これは、現在のファイルに書き込むことができます、あなたのデータフレームの前に空白を含む文字列が含まれていると

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

with open("/tmp/test.csv", "w") as f: 
    print(re.sub("[ \t]+", ",", 
       df.to_string(formatters={"b": printInt}, na_rep="NaN")), 
      file=f) 

が得られます:あなたは、あなただけの正規表現を変更することができ、CSVファイルにNaN年代を維持したいです堅牢なソリューションはそれほど簡単ではありません。次のエントリの開始を示す、すべての値の前に別の文字を挿入できます。すべての文字列に空白が1つしかない場合は、別の空白を使用することができます。これは、これにコードを変更します

与えるだろう
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 
+0

最後の例は私が望んでいたものではなく、私が避けたかったものです。したがって、NaNはそのように表現されるべきです。また、正規表現に複数の単語からなる列名を分割しない方法はありますか? – Alarik

+0

私はカラム名の空白を許可し、NaNを保持するように答えを更新しました(私はあなたが 'df'のままにしておきたいと思っていました)。これは役に立ちますか? – jotasi

+0

私はあなたの答えを受け入れました。私の問題を解決してくれましたが、恐ろしい回避策が残っています。なぜなら、数十列のフォーマッタを指定しなければならなかったからです;)二重スペーシングが問題になるカラム名やセルエントリが長すぎる場合(カラム内に1つのスペースしか残さないため)、pandasの 'to_string'関数を使用します。ご協力ありがとうございました! – Alarik

1

を多分これは仕事ができる:

あなたの出力は次のようなものでなければなりません
pd.set_option('precision',15) 
df = pd.DataFrame({'a':[1.25, 2.54], 'b':[1424380449437, 1425510731187]}) 
fg = df.applymap(lambda x: str(x)) 
fg.loc[2] = np.NaN 
fg.to_csv('test.csv', na_rep='NaN') 

(私は上ですa mac):

enter image description here

+0

しかし、この場合、 'NaN'を挿入する前にDataFramesエントリを文字列に変更する必要がありますか? – jotasi

+2

@jotasiはい、それ以外の場合は精度が失われます。私はそれがあなたの代わりかもしれないと考えました – erasmortg

+0

あなたのご意見ありがとうございますが、これは私のためには機能しません - 私の元のデータフレームはNaNを持っています。力をフロートにキャスト。 – Alarik

関連する問題