Преобразовать строку numpy.ndarray в float numpy.ndarray - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть одна проблема. Как я могу конвертировать:

import numpy as np

a = np.array([['0.1 0.2 0.3'], ['0.3 0.4 0.5'], ['0.5 0.6 0.7']])

Кому:

b = np.array([[0.1,0.2,0.3], [0.3,0.4,0.5], [0.5,0.6,0.7]])

Ответы [ 5 ]

1 голос
/ 15 июля 2019

Я оставляю этот ответ для справки тем, кто ищет векторизованный подход 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')
0 голосов
/ 10 апреля 2019

сначала вы отобразите каждый элемент в массиве, разбивая его на строки с плавающей точкой, затем примените функцию x.astype(np.float) для преобразования в число с плавающей точкой

import  numpy as np

x = np.array([['0.1 0.2 0.3'], ['0.3 0.4 0.5'], ['0.5 0.6 0.7']])    
x = np.array(list(map(lambda z: z[0].split(),x)))
y = x.astype(np.float)
print(y)

result:

[[0.1 0.2 0.3]
 [0.3 0.4 0.5]
 [0.5 0.6 0.7]]
0 голосов
/ 10 апреля 2019

Вот возможный подход:

import numpy as np
a = np.array([['0.1 0.2 0.3'], ['0.3 0.4 0.5'], ['0.5 0.6 0.7']])

# Create a placeholder list
b = []

for element in a:
  # use a list comprehension to
  #     * take the zeroeth element in each row of the 'a' array and
  #       split the string on spaces
  #     * parse through each substring thus produced
  #     * convert each of those substrings into floats
  #     * store it in the list called temp.

  temp = [float(num) for num in element[0].split()]

  # Add each temp list to the parent list 'b'
  b.append(temp)

# Convert b into an np.array
b = np.array(b)

Без комментариев

Это выглядит так:

b = []

for element in a:
    temp = [float(num) for num in element[0].split(' ')]
    b.append(temp)
b = np.array(b)

Выход:

array([[0.1, 0.2, 0.3],
       [0.3, 0.4, 0.5],
       [0.5, 0.6, 0.7]])

Альтернативный подход:

Мне, как правило, нравится этот подход, так как он использует нативные способности натива.Я не проверял его, но я не удивлюсь, если это приведет к ускорению процесса преобразования для больших массивов.

# transform 'a' to an array of rows full of individual strings
# use the .astype() method to then cast each value as a float
a = np.array([row[0].split() for row in a])
b = a.astype(np.float)

Hattip to @ ahmed_yousif

0 голосов
/ 10 апреля 2019

Вы можете сделать это с помощью вложенных списков, а затем изменить их.

b = [ float(h) for j in [i[0].split(" ") for i in a  ]for h in j ]
b = np.asarray(b).reshape(3,3)

Надеюсь, это поможет.

@ E.Решение Ducateme также довольно сжато.

0 голосов
/ 10 апреля 2019
b = []
for ai in a:
  temp=[]
  for b in ai[0].split(' '):
     temp.append(float(b))
  b.append(temp)

b = np.array(b)

Вы перебираете все строки, разбиваете их на пробелы и вводите их как плавающие

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...