Заменить один символ в списке строк Numpy - PullRequest
1 голос
/ 04 октября 2019

У меня есть массив Numpy объектов datetime64, которые мне нужно преобразовать в определенный формат времени гггг-мм-дд, чч: мм: SS.SSS Numpy имеет функцию с именем datetime_as_string, которая выводит ISO8601 (гггг-мм-ddTHH: MM: SS.SSS) время, которое очень близко к тому, что я хочу, с той лишь разницей, что есть T, где я хочу запятую.

Есть ли способ быстро поменять местами "T"для ","? Вот пример набора данных:

offset = np.arange(0, 1000)
epoch = np.datetime64('1970-01-01T00:00:00.000')
time_objects = epoch + offset.astype('timedelta64[ms]')
time_strings = np.datetime_as_string(time_objects)

Я успешно использовал лямбду и понимание списка, но кажется неудобным переключаться назад и вперед из списка Python в массив Numpy.

f = lambda x: x[:10] + ',' + x[11:]
np.array([f(x) for x in time_strings])

Я знаю, что в некоторых случаях лямбды могут быть применены "напрямую" к массиву Numpy, но в этом случае это не работает. f(time_strings) создает ошибку типа. Есть какие-нибудь мысли?

Я знаю, что могу перевести обратно в Python datetime (откуда я иду) или использовать Pandas. Но функция datetime_as_string действительно быстрая, и я бы хотел придерживаться решения Numpy.

--- Выводы, основанные на ответах ---
Оказывается, что взгляд Пола на сотворение чёрной магии был 75xбыстрее, чем мое понимание списка, и в 100 раз быстрее, чем np.char.replace(). Вот результаты этих трех методов (все были инициализированы с помощью вышеуказанного набора данных, но с 1000000 элементами).

start = time.time()
time_strings[..., None].view('U1')[..., 10] = ','
print(time.time() - start)
0.016000747680664062 seconds

start = time.time()
f = lambda x: x[:10] + ',' + x[11:]
time_strings = np.array([f(x) for x in time_strings])
print(time.time() - start, 'seconds')
1.1740672588348389 seconds

start = time.time()
time_strings = np.char.replace(time_strings,'T',',')
print(time.time() - start, 'seconds')
1.4980854988098145 seconds

Ответы [ 2 ]

3 голосов
/ 04 октября 2019

Вы можете использовать Viewcasting, чтобы получить доступ к отдельным персонажам:

time_strings[...,None].view('U1')[...,10] = ','

изменения time_strings на месте.

2 голосов
/ 04 октября 2019
In [309]: np.char.replace(time_strings,'T',',')                                 
Out[309]: 
array(['1970-01-01,00:00:00.000', '1970-01-01,00:00:00.001',
       '1970-01-01,00:00:00.002', '1970-01-01,00:00:00.003',
       '1970-01-01,00:00:00.004', '1970-01-01,00:00:00.005',
       '1970-01-01,00:00:00.006', '1970-01-01,00:00:00.007',
       ....

Но на месте @ PaulPanzer гораздо быстрее (даже немного более непонятно):

In [316]: %%timeit temp=time_strings.copy() 
     ...: temp[...,None].view('U1')[...,10] = ','                                                                      
8.48 µs ± 34.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [317]: timeit np.char.replace(time_strings,'T',',')                          
1.23 ms ± 1.12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
...