Я оставляю этот ответ для справки тем, кто ищет векторизованный подход NumPy.TL; DR: это не быстро, используйте np.array([row[0].split() for row in a], dtype=float)
как в принятый ответ .
Я искал векторизованный подход к этой проблеме и придумал следующеерешения.
Использование np.char.split
:
import numpy as np
def to_numeric1(array, sep=' ', dtype=np.float):
"""
Converts an array of strings with delimiters in it
to an array of specified type
"""
split = np.char.split(array, sep=sep)
without_lists = np.array(split.tolist())
corrected_dimension = np.squeeze(without_lists)
return corrected_dimension.astype(dtype)
И использование pd.Series.str.split
:
import pandas as pd
def by_pandas(array, sep=' ', dtype=np.float):
df = pd.DataFrame(array)
return df[0].str.split(pat=sep, expand=True).to_numpy(dtype=dtype)
К сожалению, обарешения на медленнее , чем нативные циклы Python, как в E.Ответ Ducateme :
a = np.array([['0.1 0.2 0.3'], ['0.3 0.4 0.5'], ['0.5 0.6 0.7']]*10000)
%%timeit
native_python_loop(a)
# 57.8 ms ± 526 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
to_numeric1(a)
# 86.6 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
to_numeric2(a)
# 79.8 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Как указано в комментарии от hpaulj :
Функции np.char
применяют строковые методы Python к каждому элементумассива.Они удобны, но не улучшают скорость.NumPy не имеет быстро скомпилированного кода, который работает с содержимым строк.Это зависит от существующего кода Python для этого.«векторизация» в обычном числовом смысле для строк не существует.
В идеале первое решение может быть таким же быстрым, как нативные циклы Python, и иметь меньше строк кода.Проблема с возвращаемыми значениями np.char.split
:
>>> a = np.array([['0.1 0.2 0.3'], ['0.3 0.4 0.5'], ['0.5 0.6 0.7']])
>>> np.char.split(a)
array([[list(['0.1', '0.2', '0.3'])],
[list(['0.3', '0.4', '0.5'])],
[list(['0.5', '0.6', '0.7'])]], dtype=object)
Возвращает массив NumPy массивов списков строк NumPy, которые должны быть дополнительно обработаны в обычный двумерный массив NumPy, и я предполагаю, что эта обработказанимает много времени.Как сказал hpaulj : "[i.split() for i in a]
и np.char.split(a)
занимают в основном одно и то же время "
Существует проблема в GitHub , которая предлагаетизменяет эту функцию, поэтому вместо нее возвращается следующее:
array([['0.1', '0.2', '0.3'],
['0.3', '0.4', '0.5'],
['0.5', '0.6', '0.7']], dtype='<U3')