Вопрос по arrays, multidimensional-array, python, numpy – Программно добавлять имена столбцов в Numpy ndarray

12

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

Вот мой код.

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)

& quot; печать data.dtype.names & quot; также возвращает ожидаемый результат.

Но когда я начинаю называть столбцы по именам их полей, происходят странные вещи. & Quot; столбец & quot; все еще массив с 108 столбцами ...

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

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

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

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

Ваш Ответ

2   ответа
14

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

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

NumPy arrays only contain elements of a single type. If you need spreadsheet-like "columns", this type must be some tuple-like type. Such arrays are called Structured Arrays, because their elements are structures (i.e. tuples).

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

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

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

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

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

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

Вы также можете проверить ответы на несколько вопросов Stackoverflow, в том числеПреобразование двумерного массива в структурный массив а такжеКак преобразовать обычный массив NumPy для записи массива?.

Спасибо - это помогает прояснить ситуацию концептуально. Но у меня все еще есть некоторые вопросы по этому конкретному делу. Здесь все мои столбцы являются числами с плавающей точкой, и я собираюсь много умножать матрицы, поэтому я хочу сохранить структуру 2d-массива - нет необходимости в структурированном массиве. Все, что я хочу сделать, это добавить имена полей. Это возможно? Abe
Примечание: genfromtxt импортирует CSV-файл в формате структурированного кортежа numpy. Я перепробовал все, что мог придумать, чтобы импортировать имена полей в формате массива, но ничего не получалось. Abe
@Abe: Технически, я не хочу усложнять вещи, чем они, но учтите, что вы можете иметь 2D (или n-мерный) структурированный массив. Тем не менее, каждая ячейка будет содержатьtuple, Пример:arr = zeros((3, 5), dtype=[('x', int), ('y', float)])со структурой доступа вродеa['x'], который возвращает двумерный массив целых чисел.
@Abe: О вашем втором вопросе: выcannot иметь & quot; имена полей в (2D) формате массива & quot ;. Эта концепция недопустима в NumPy (это концепция электронных таблиц). Вам нужен 2D-массив неструктурированных / именованных столбцов (вашdata массив) или его 1D структурированные / именованные столбцы (результатview() в моем ответе). Я надеюсь, что это поможет прояснить ситуацию. :)
@Abe: Вы все еще можете выполнять матричные умножения:view() это просто другой способ взглянуть наsame данные. Таким образом, вы можете работать как с исходным массивом данных, так и сview()Одновременно массив (первый массив 2D, второй - 1D и структурированный).
3

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

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

РЕДАКТИРОВАТЬ:

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

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names])
Так значит ли это, что на ndarrays можно ссылаться по именам полей, если они приводятся как кортежи, ИЛИ по ссылкам по id полей, когда они приводятся как массивы - но никогда не оба? Кажется, так оно и работает, но я не вижу ничего подобного в документации. Abe
Я начинаю задаваться вопросом, является ли это ошибкой. Это очень странное поведение, когда конструктор массива действует по-разному в зависимости от типа вложенной структуры, в которую вы передаете.
@ user545424: Вы можете понять это поведение, если знаете принципы, на которых основан NumPy (например, вы можете проверить мой ответ). В двух словах: tuple () является своего рода «фундаментальным типом». (например, с плавающей точкой), для NumPy (так что вы получаете некий структурированный массив при передаче кортежей), тогда как передача списков или массивов в качестве входных данных означает «добавить другое измерение» в массив (вы получите массив чисел, как правило).

Похожие вопросы