3

Pandas 0.12.0 を使用していますが、シリーズまたはデータフレームを json に変換するときにドキュメントと矛盾する動作が見られます。

null 値を含むいくつかの日付を含むシリーズを作成すると、次のようになります。

>>> s = pandas.Series(data=[datetime.datetime.now(), datetime.datetime.now(), None])
>>> s
0    2013-11-07 16:10:47.530771
1    2013-11-07 16:10:47.530782
2                          None
dtype: object

http://pandas.pydata.org/pandas-docs/dev/io.html#writing-jsonによると、json に変換すると、None、NaT、NaN の値は null として出力されるはずです。

次に to_json を出力すると、予想どおり、3 番目のエントリで null が返されます。

>>> s.to_json()
'{"0":1383840647530771000,"1":1383840647530782000,"2":null}'

ただし、他の計算ではデータ型が datetime64[ns] であることを確認する必要があるため、次のように Pandas でフィールドを datetime に変換します。

>>> t = pandas.to_datetime(s)
>>> t
0   2013-11-07 16:10:47.530771
1   2013-11-07 16:10:47.530782
2                          NaT
dtype: datetime64[ns]

None は NaT になりました。これは一貫性があり、期待されています。次に、json を再度出力しようとすると、期待していた null ではなく、NaT 値に負の値が返されます。

>>> t.to_json()
'{"0":1383840647530771000,"1":1383840647530782000,"2":-9223372036854775808}'

日付をフォーマットしようとするため、iso フォーマットを使用するとさらに悪化しますが、ほとんどのパーサーは出力日付を処理する方法を理解できず、これによりあらゆる種類の混乱が発生します。

>>> t.to_json(date_format='iso')
'{"0":"2013-11-07T16:10:47.530771","1":"2013-11-07T16:10:47.530782","2":"0001-255-255T00:00:00"}'

ここでどのように進めるべきかについて何か考えはありますか? ありがとう!

編集

これは pandas.NaT の文字列表現に問題があるように見えますか?

>>> str(pandas.NaT)
'0001-255-255 00:00:00'
4

2 に答える 2

3

少しハックですが、これを行うことができます

 In [13]: s = Series(pd.to_datetime(['20130101',None]))

 In [14]: s
 0   2013-01-01 00:00:00 
 1                   NaT
 dtype: datetime64[ns]

 In [15]: def f(x):
             if isnull(x): 
                return 'null'
             return x.isoformat()    ....: 

 In [16]: s.apply(f).to_json() 

 Out[16]:
 '{"0":"2013-01-01T00:00:00","1":"null"}'
于 2013-11-07T21:46:58.527 に答える
2

カスタム エンコーダーを作成するだけです。

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if pd.isnull(obj):
            return None
        elif isinstance(obj, datetime):
            return obj.isoformat()
        elif isinstance(obj, date):
            return obj.isoformat()
        elif isinstance(obj, timedelta):
            return (datetime.min + obj).time().isoformat()
        else:
            return super(CustomEncoder, self).default(obj)

次に、それを使用してデータフレームをエンコードします。

df_as_dict = df.to_dict(outtype = 'records')  # transform to dict

df_as_json = CustomEncoder().encode(df_as_dict) #transform to json

エンコーダーがデータを標準化したので、通常のデコーダーはそれをデータフレームに戻す際に正常に動作します。

result_as_dict = json.JSONDecoder().decode(df_as_json) # decode back to dict

result_as_df = pd.DataFrame(result_as_dict)  # transform dict back to dataframe

もちろん、これは、エンコードする前にデータフレームをより大きな辞書に入れた場合にも機能します。

input_dict = {'key_1':val_1,'key_2':val_2,...,'df_as_dict':df_as_dict}
input_json = CustomEncoder().encode(input_dict)
input_json_back_as_dict = json.JSONDecoder().decode(input_json)
input_df_back_as_dict = input_json_back_as_dict['df_as_dict']
input_df_back_as_df = pd.DataFrame(input_df_back_as_dict)
于 2015-12-28T07:19:56.803 に答える