使用对象数组进行条件索引



我有一个日期时间对象的 1D numpy 数组,我想抓取所有具有特定月份的对象。我可以通过迭代整个数组来做到这一点:

new_times = []
for time in times:
if time.month == 1:
new_times.append(time)

但这不是很有效,而且看起来也不是很python化。如果这是一个整数月份数组,我可以做类似的事情

arr = np.array([1,1,2,3,4,5,6,1,7,4,8,1])
new_arr = arr[np.where(arr == 1)]

但是,在调用数组对象的属性时,此方法不起作用。有没有一种很好的方法来搜索所有具有特定对象属性的numpy数组元素?

一般来说,我不知道你能比使用vectorizefrompyfunc(然后使用标准的 numpy 技术进行过滤等(做得更好:

例如

import datetime
M = np.array([datetime.datetime(1980,i,i) for i in range(1,4)])
M
# array([datetime.datetime(1980, 1, 1, 0, 0),
#        datetime.datetime(1980, 2, 2, 0, 0),
#        datetime.datetime(1980, 3, 3, 0, 0)], dtype=object)
import operator as op
np.frompyfunc(op.attrgetter("month"),1,1)(M)
# array([1, 2, 3], dtype=object)
np.vectorize(op.attrgetter("month"),otypes=(int,))(M)
# array([1, 2, 3])

在您的具体情况中:

Mnp = M.astype("M8[M]")
Mnp - Mnp.astype("M8[Y]") + 1
# array([1, 2, 3], dtype='timedelta64[M]')

在这里使用hpaulj的方法使用列表理解既简单又快速:

>>> import numpy as np
>>> import datetime as dt
>>> a=np.array([dt.datetime(month=1,day=2,year=2020),dt.datetime(month=2,day=12,year=2019),dt.datetime(month=8,day=26,year=1952)])
>>> [e for e in a.tolist() if e.month<5]
[datetime.datetime(2020, 1, 2, 0, 0), datetime.datetime(2019, 2, 12, 0, 0)]

如果您只想要索引:

>>> [i for i,e in enumerate(a.tolist()) if e.month<5]
[0, 1]

在这里使用pandas.Series可能是一个很好的帮手,

from datetime import datetime
import numpy as np
import pandas as pd
a = np.array([datetime(2020, m, 1) for m in range(1, 5)])
s = pd.Series(a)

现在,您可以访问月份

s.dt.month
# 0    1
# 1    2
# 2    3
# 3    4
# dtype: int64
a[s.dt.month < 3]
# array([datetime.datetime(2020, 1, 1, 0, 0),
#        datetime.datetime(2020, 2, 1, 0, 0)], dtype=object)

这将适用于 datetime.datetime 对象数组以及 np.datetime64。但与往常一样,便利是有代价的,因此列表理解(在 datetime.datetime 的情况下(、np.vectorizenp.frompyfunc很可能会运行得更快。

最新更新