Почему нельзя объединить datetime64 с другими массивами с помощью np.c_? - PullRequest
0 голосов
/ 03 октября 2019

Я мигрирую из Matlab ... Используя Jupyter Lab в Windows 10.

Допустим, у меня есть временной ряд с массивом datetime64 и некоторыми другими данными

t = np.arange('2010-09-01','2010-09-02', dtype='datetime64[6h]')

d = np.linspace(0,1,len(t))

Я хочу объединить оба, чтобы сохранить продолжение работы в другом блокноте (я знаю, что есть и другие способы сделать это!). Сначала я преобразовываю их в массивы столбцов

t_col = t.reshape(-1,1)
d_col = d.reshape(-1,1)

и объединяю

m = np.c_[t_col, d_col]

и получаю

TypeError                                 Traceback (most recent call last)
<ipython-input-28-5bbb5e23249f> in <module>
----> 1 m = np.c_[t_col, d_col]

c:\Python37_32\lib\site-packages\numpy\lib\index_tricks.py in __getitem__(self, key)
    333                 objs[k] = objs[k].astype(final_dtype)
    334 
--> 335         res = self.concatenate(tuple(objs), axis=axis)
    336 
    337         if matrix:

TypeError: invalid type promotion

, но если я сначала преобразую datetime64 в datetime

t_col2 =t_col.astype('datetime64[h]').tolist()

m = np.c_[t_col2, d_col]

это работает.

Вопрос: Почему я не могу объединить массивы, когда data & time - datetime64? Почему мне нужно преобразовать его в datetime?

1 Ответ

0 голосов
/ 03 октября 2019
In [266]: t = np.arange('2010-09-01','2010-09-02', dtype='datetime64[6h]') 
     ...:  
     ...: d = np.linspace(0,1,len(t))                                           
In [267]: t                                                                     
Out[267]: 
array(['2010-09-01T00', '2010-09-01T06', '2010-09-01T12', '2010-09-01T18'],
      dtype='datetime64[6h]')
In [268]: d                                                                     
Out[268]: array([0.        , 0.33333333, 0.66666667, 1.        ])

Использование vstack вместо c_ (просто для удобства):

In [269]: np.vstack((t,d))                                                      
...
<__array_function__ internals> in concatenate(*args, **kwargs)

TypeError: invalid type promotion

Ошибка возникает из-за того, что результатом должен быть один dtype, либо с плавающей запятой, либо datetime64,Для массивов numpy требуется унифицированный тип d (например, MATLAB matrix).

С tolist или astype(object) массив datetime64 превращается в datatime объекты. Их можно объединить с помощью чисел с плавающей точкой, а также преобразовать в объекты:

In [270]: np.vstack((t.tolist(),d))                                             
Out[270]: 
array([[datetime.datetime(2010, 9, 1, 0, 0),
        datetime.datetime(2010, 9, 1, 6, 0),
        datetime.datetime(2010, 9, 1, 12, 0),
        datetime.datetime(2010, 9, 1, 18, 0)],
       [0.0, 0.3333333333333333, 0.6666666666666666, 1.0]], dtype=object)

In [271]: np.vstack((t.astype(object),d))                                       
Out[271]: 
array([[datetime.datetime(2010, 9, 1, 0, 0),
        datetime.datetime(2010, 9, 1, 6, 0),
        datetime.datetime(2010, 9, 1, 12, 0),
        datetime.datetime(2010, 9, 1, 18, 0)],
       [0.0, 0.3333333333333333, 0.6666666666666666, 1.0]], dtype=object)

Этот массив dtype объекта похож на MATLAB cell, содержащий различные элементы.

Другой вариант - создать структурированный массив(вроде как MATLAB struct):

In [274]: arr  = np.zeros(4, dtype=[('t',t.dtype), ('d',d.dtype)])              
In [275]: arr                                                                   
Out[275]: 
array([('1970-01-01T00', 0.), ('1970-01-01T00', 0.),
       ('1970-01-01T00', 0.), ('1970-01-01T00', 0.)],
      dtype=[('t', '<M8[6h]'), ('d', '<f8')])
In [276]: arr['t']=t; arr['d']=d                                                
In [277]: arr                                                                   
Out[277]: 
array([('2010-09-01T00', 0.        ), ('2010-09-01T06', 0.33333333),
       ('2010-09-01T12', 0.66666667), ('2010-09-01T18', 1.        )],
      dtype=[('t', '<M8[6h]'), ('d', '<f8')])

edit


Другой способ построить структурированный массив из этих двух массивов:

In [286]: import numpy.lib.recfunctions as rf     
In [293]: rf.merge_arrays((t,d))                                                
Out[293]: 
array([('2010-09-01T00', 0.        ), ('2010-09-01T06', 0.33333333),
       ('2010-09-01T12', 0.66666667), ('2010-09-01T18', 1.        )],
      dtype=[('f0', '<M8[6h]'), ('f1', '<f8')])

Внутренне это похоже на то, что я впервые продемонстрировал.

...