代码之家  ›  专栏  ›  技术社区  ›  Pythonist

numpy数组中元素的访问属性

  •  1
  • Pythonist  · 技术社区  · 7 年前

    我有一个numpy数组,其中包含 cftime 班级。

    In [1]: a
    Out[1]: 
    array([cftime.DatetimeNoLeap(2000, 1, 1, 11, 29, 59, 999996, 5, 1),
           cftime.DatetimeNoLeap(2000, 1, 2, 11, 29, 59, 999996, 6, 2),
           cftime.DatetimeNoLeap(2000, 1, 3, 11, 29, 59, 999996, 0, 3)],
          dtype=object)
    
    In [2]: type(a[0])
    Out[2]: cftime._cftime.DatetimeNoLeap
    

    每个对象都有一个属性 month .

    a[0].month
    Out[66]: 1
    

    我想得到一个形状相同的新numpy数组,但对原始数组的每个元素都填充了这个属性。类似的东西 b=a.month . 但很明显这失败了,因为 a 是一个没有 属性。我怎样才能达到这个结果?

    PS:当然,我可以用一个普通的python循环来完成这项工作,但是我想采用一种完全麻木的方法:

    b=np.zeros_like(a, dtype=int)
    for i in range(a.size):
        b[i] = a[i].month
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   yatu Sayali Sonawane    7 年前

    你可以使用 np.vectorize ,以便将函数映射到数组中的每个元素。对于这种情况,可以定义自定义 lambda 函数提取每个条目的月份 lambda x: x.month :

    np.vectorize(lambda x: x.month)(a)
    array([1, 1, 1])
    
        2
  •  0
  •   hpaulj    7 年前

    我没有 cftime 已安装,因此将用常规的日期时间对象演示。

    首先创建一个日期时间对象数组-使用numpy自己的日期时间数据类型的懒惰方式:

    In [599]: arr = np.arange('2000-01-11','2000-12-31',dtype='datetime64[D]')
    In [600]: arr.shape
    Out[600]: (355,)
    

    从中生成对象数据类型数组:

    In [601]: arrO = arr.astype(object)
    

    以及日期列表:

    In [602]: alist = arr.tolist()
    

    定期列表理解的时间:

    In [603]: timeit [d.month for d in alist]
    20.1 µs ± 62.7 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    对象数据类型数组上的列表理解通常较慢(但比常规数组上的列表理解快):

    In [604]: timeit [d.month for d in arrO]
    30.7 µs ± 266 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    frompyfunc -在这里,它是慢的;其他时候,我看到它比列表理解快2倍:

    In [605]: timeit np.frompyfunc(lambda x: x.month, 1,1)(arrO)
    51 µs ± 32.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    vectorize 总是(几乎)慢于 从聚氧乙烯 (即使它使用 从聚氧乙烯 对于实际迭代:

    In [606]: timeit np.vectorize(lambda x: x.month, otypes=[int])(arrO)
    76.7 µs ± 123 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    以下是数组和列表的示例:

    In [607]: arr[:5]
    Out[607]: 
    array(['2000-01-11', '2000-01-12', '2000-01-13', '2000-01-14',
           '2000-01-15'], dtype='datetime64[D]')
    In [608]: arrO[:5]
    Out[608]: 
    array([datetime.date(2000, 1, 11), datetime.date(2000, 1, 12),
           datetime.date(2000, 1, 13), datetime.date(2000, 1, 14),
           datetime.date(2000, 1, 15)], dtype=object)
    In [609]: alist[:5]
    Out[609]: 
    [datetime.date(2000, 1, 11),
     datetime.date(2000, 1, 12),
     datetime.date(2000, 1, 13),
     datetime.date(2000, 1, 14),
     datetime.date(2000, 1, 15)]
    

    从聚氧乙烯 矢量化 当需要广播和多维数组的通用性时,最好使用。对于一维数组,列表理解几乎总是更好的。

    更公平地 从聚氧乙烯 ,我应该从列表理解返回一个数组:

    In [610]: timeit np.array([d.month for d in arrO])
    50.1 µs ± 36.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    若要获得最快的日期,请使用 datatime64 DTYPE而不是Object DTYPE。这使得编译后的numpy代码得到了更多的使用。

    In [611]: timeit arr = np.arange('2000-01-11','2000-12-31',dtype='datetime64[D]'
         ...: )
    3.16 µs ± 51 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    In [616]: arr.astype('datetime64[M]')[::60]
    Out[616]: 
    array(['2000-01', '2000-03', '2000-05', '2000-07', '2000-09', '2000-11'],
          dtype='datetime64[M]')