Загрузка текстового файла, содержащего как float, так и строку, используя numpy.loadtxt

У меня есть текстовый файл data.txt, который содержит:

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
5.8,2.7,4.1,1.0,Iris-versicolor
6.2,2.2,4.5,1.5,Iris-versicolor
6.4,3.1,5.5,1.8,Iris-virginica
6.0,3.0,4.8,1.8,Iris-virginica

Как загрузить эти данные с помощью numpy.loadtxt(), чтобы я получил массив NumPy после загрузки, например [['5.1' '3.5' '1.4' '0.2' 'Iris-setosa'] ['4.9' '3.0' '1.4' '0.2' 'Iris-setosa'] ...]?

Я пробовал

np.loadtxt(open("data.txt"), 'r',
           dtype={
               'names': (
                   'sepal length', 'sepal width', 'petal length',
                   'petal width', 'label'),
               'formats': (
                   np.float, np.float, np.float, np.float, np.str)},
           delimiter= ',', skiprows=0)

Ответы

Ответ 1

Если вы используете np.genfromtxt, вы можете указать dtype=None, который будет сообщать genfromtxt, чтобы разумно угадать dtype каждого столбца, Наиболее удобно, это избавляет вас от того, что вы указываете количество байтов, необходимых для столбца строки. (Опущение числа байтов, указав, например, np.str, не работает.)

In [58]: np.genfromtxt('data.txt', delimiter=',', dtype=None, names=('sepal length', 'sepal width', 'petal length', 'petal width', 'label'))
Out[58]: 
array([(5.1, 3.5, 1.4, 0.2, 'Iris-setosa'),
       (4.9, 3.0, 1.4, 0.2, 'Iris-setosa'),
       (5.8, 2.7, 4.1, 1.0, 'Iris-versicolor'),
       (6.2, 2.2, 4.5, 1.5, 'Iris-versicolor'),
       (6.4, 3.1, 5.5, 1.8, 'Iris-virginica'),
       (6.0, 3.0, 4.8, 1.8, 'Iris-virginica')], 
      dtype=[('sepal_length', '<f8'), ('sepal_width', '<f8'), ('petal_length', '<f8'), ('petal_width', '<f8'), ('label', 'S15')])

Если вы хотите использовать np.loadtxt, то для исправления кода с минимальными изменениями вы можете использовать:

np.loadtxt("data.txt",
   dtype={'names': ('sepal length', 'sepal width', 'petal length', 'petal width', 'label'),
          'formats': (np.float, np.float, np.float, np.float, '|S15')},
   delimiter=',', skiprows=0)

Основное отличие, если просто изменить np.str на |S15 (15-байтовая строка).

Также отметим, что open("data.txt"), 'r' должен быть open("data.txt", 'r'). Но так как np.loadtxt может принимать имя файла, вам действительно не нужно использовать open вообще.

Ответ 2

Кажется, что сохранение числа и текста вместе привело к таким большим неприятностям - если вы в конечном итоге решите их разделить, мое обходное решение:

values = np.loadtxt('data', delimiter=',', usecols=[0,1,2,3])
labels = np.loadtxt('data', delimiter=',', usecols=[4])