Подтвердить что ты не робот

Программно добавлять имена столбцов в numpy ndarray

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

Вот мой код.

data = np.genfromtxt(csv_file, delimiter=',', dtype=np.float, skip_header=1)

#Add headers
csv_names = [ s.strip('"') for s in file(csv_file,'r').readline().strip().split(',')]
data = data.astype(np.dtype( [(n, 'float64') for n in csv_names] ))

Диагностика на основе измерений соответствует ожидаемым:

print len(csv_names)
>> 108
print data.shape
>> (1652, 108)

"print data.dtype.names" также возвращает ожидаемый результат.

Но когда я начинаю называть столбцы своими именами полей, случаются сумасшедшие вещи. "Столбец" по-прежнему представляет собой массив с 108 столбцами...

print data["EDUC"].shape
>> (1652, 108)

... и он содержит больше отсутствующих значений, чем в наборе данных есть строки.

print np.sum(np.isnan(data["EDUC"]))
>> 27976

Любая идея, что здесь происходит не так? Добавление заголовков должно быть тривиальной операцией, но я борюсь с этой ошибкой в ​​течение нескольких часов. Помогите!

4b9b3361

Ответ 1

Проблема заключается в том, что вы думаете о сетях, подобных массивам, тогда как NumPy использует разные понятия.

Вот что вы должны знать о NumPy:

  • Массивы NumPy содержат только элементы одного типа.
  • Если вам нужны таблицы, похожие на таблицы, этот тип должен быть похожим на тип типа. Такие массивы называются структурированными массивами, потому что их элементами являются структуры (т.е. Кортежи).

В вашем случае NumPy, таким образом, возьмет ваш двумерный регулярный массив и создаст одномерный массив, тип которого является 108-элементным кортежем (массив электронной таблицы, о котором вы думаете, является двумерным).

Эти варианты, вероятно, были сделаны по соображениям эффективности: все элементы массива имеют один и тот же тип и поэтому имеют одинаковый размер: к ним можно получить доступ на низком уровне очень просто и быстро.

Теперь, как показал user545424, есть простой ответ NumPy на то, что вы хотите сделать (genfromtxt() принимает аргумент names с именами столбцов).

Если вы хотите преобразовать свой массив из обычного NumPy ndarray в структурированный массив, вы можете сделать:

data.view(dtype=[(n, 'float64') for n in csv_names]).reshape(len(data))

(вы были близки: вы использовали astype() вместо view()).

Вы также можете проверить ответы на несколько вопросов Stackoverflow, включая Преобразование массива 2D numpy в структурированный массив и как преобразовать обычный массив numpy в запись массива?.

Ответ 2

К сожалению, я не знаю, что происходит, когда вы пытаетесь добавить имена полей, но я знаю, что вы можете построить массив, который хотите получить непосредственно из файла, через

data = np.genfromtxt(csv_file, delimiter=',', names=True)

EDIT:

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

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names])