我正在寫一個函數來從數組中提取datetimes中的值。我希望函數能夠在Pandas DataFrame或numpy ndarray上運行。Python/Numpy:向量化和項目中類型轉換的問題
這些值應該以與Python datetime屬性相同的方式返回,例如,
from datetime import datetime
dt = datetime(2016, 10, 12, 13)
dt.year
=> 2016
dt.second
=> 0
對於一個數據幀,這是相當容易使用applymap()
(雖然有可能是一個更好的方法)來處理。我嘗試了使用vectorize()
的numpy ndarrays的相同方法,並且遇到了問題。取而代之的是我期待的價值觀,我最終得到的是非常大的整數,有時候是負值。
起初,這很令人費解,但我知道發生了什麼事情:矢量化函數使用item
而不是__get__
將值從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()
?
謝謝!
最小代碼例如:
## 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