配列のdatetimesから値を抽出する関数を書いています。私は、この機能をPandas DataFrameまたはnumpy ndarrayで操作したいと考えています。Python/Numpy:ベクトル化とアイテムの型変換の問題
値は、Pythonの日時プロパティと同じ方法で返す必要があります。データフレームのために
from datetime import datetime
dt = datetime(2016, 10, 12, 13)
dt.year
=> 2016
dt.second
=> 0
これは(もより良い方法があるかもしれませんが)applymap()
を使用して処理するために合理的に簡単です。私はvectorize()
を使用してnumpy ndarraysに対して同じアプローチを試みましたが、問題が発生しています。私が期待していた値の代わりに、非常に大きな整数で終わることもあります。
最初はかなり困惑しましたが、何が起きているのか分かりました。ベクトル化された関数は__get__
の代わりにitem
を使用して、ndarrayから値を取得しています。これは、自動的に各datetime64
オブジェクトはlong
に変換すると思われる:
nd[1][0]
=> numpy.datetime64('1986-01-15T12:00:00.000000000')
nd[1].item()
=> 506174400000000000L
長いはエポック(1970-01-01T00:00:00)以降のナノ秒数であると思われます。ラインのどこかで、値は整数に変換され、オーバーフローして負の数になります。
それが問題です。誰かが私にそれを解決するのを助けてくれる?私が考えることができるのは、変換を手動で行うことだけですが、これは実質的にdatetime
モジュールのチャンクを再実装することを意味します。
vectorize
には、item()
を使用しない代替手段がありますか?
ありがとうございます!
最小限のコード例:PY3で
## DataFrame works fine
import pandas as pd
from datetime import datetime
df = pd.DataFrame({'dts': [datetime(1970, 1, 1, 1), datetime(1986, 1, 15, 12),
datetime(2016, 7, 15, 23)]})
exp = pd.DataFrame({'dts': [1, 15, 15]})
df_func = lambda x: x.day
out = df.applymap(df_func)
assert out.equals(exp)
## numpy ndarray is more difficult
from numpy import datetime64 as dt64, timedelta64 as td64, vectorize # for brevity
# The unary function is a little more complex, especially for days and months where the minimum value is 1
nd_func = lambda x: int((dt64(x, 'D') - dt64(x, 'M') + td64(1, 'D'))/td64(1, 'D'))
nd = df.as_matrix()
exp = exp.as_matrix()
=> array([[ 1],
[15],
[15]])
# The function works as expected on a single element...
assert nd_func(nd[1][0]) == 15
# ...but not on an ndarray
nd_vect = vectorize(nd_func)
out = nd_vect(nd)
=> array([[ -105972749999999],
[ 3546551532709551616],
[-6338201187830896640]])
おかげで@hpaulj、あなたはそこには、ベクトル化のために必要であることなかっに関する優れたポイントを作ります - 'astype(' datetime64 [$ UNIT] ') 'を使用しています(うまくいけば、私のひどく混乱した構文が見えます)。 – charrison