2013-03-22 7 views
11

У меня есть еще один основной вопрос, на который я не смог найти ответ, но кажется, что это должно быть легко сделать.Как удалить столбец из структурированного массива numpy?

Хорошо, представьте, что у вас есть структурированный массив numpy, созданный из csv с первой строкой в ​​качестве имен полей. Массив имеет форму:

dtype([('A', '<f8'), ('B', '<f8'), ('C', '<f8'), ..., ('n','<f8']) 

Теперь, скажем, вы хотите удалить из этого массива столбец 'ith'. Есть ли удобный способ сделать это?

Я хотел бы, чтобы работать, как удаление:

new_array = np.delete(old_array, 'i') 

Есть идеи?

+0

Все ли dtypes f8? –

ответ

13

Это не совсем вызов одной функции, но следующие показывает один из способов понизить I-го поля:

In [67]: a 
Out[67]: 
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
     dtype=[('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

In [68]: i = 1 # Drop the 'B' field 

In [69]: names = list(a.dtype.names) 

In [70]: names 
Out[70]: ['A', 'B', 'C'] 

In [71]: new_names = names[:i] + names[i+1:] 

In [72]: new_names 
Out[72]: ['A', 'C'] 

In [73]: b = a[new_names] 

In [74]: b 
Out[74]: 
array([(1.0, 3.0), (4.0, 6.0)], 
     dtype=[('A', '<f8'), ('C', '<f8')]) 

Закутавшись как функция:

def remove_field_num(a, i): 
    names = list(a.dtype.names) 
    new_names = names[:i] + names[i+1:] 
    b = a[new_names] 
    return b 

Это может быть более естественно удалить данное поле имя:

def remove_field_name(a, name): 
    names = list(a.dtype.names) 
    if name in names: 
     names.remove(name) 
    b = a[names] 
    return b 

Кроме того, ч вытащите drop_rec_fields function, который является частью mlab module of matplotlib.


Update: Смотрите мой ответ на How to remove a column from a structured numpy array *without copying it*? для метода создания представления подмножеств полей структурированного массива, не делая копию массива.

+0

+1 Ударьте меня на 3 минуты! – Jaime

+1

@ Jaime: Едва ли. :) Поскольку вы удалили свой ответ, я упомянул об удалении по имени поля, а не по номеру, что может быть более естественным. –

5

После гугла моего пути здесь и узнал, что мне нужно знать, от ответа Уоррена, я не мог сопротивляться размещениями более сжатой версии, с добавлением опции, чтобы удалить несколько полей эффективно на одном дыхании:

def rmfield(a, *fieldnames_to_remove): 
    return a[ [ name for name in a.dtype.names if name not in fieldnames_to_remove ] ] 

Примеры:

a = rmfield(a, 'foo') 
a = rmfield(a, 'foo', 'bar') # remove multiple fields at once 

Или, если мы действительно собираемся гольфе это, следующее эквивалентно:

rmfield=lambda a,*f:a[[n for n in a.dtype.names if n not in f]] 
+0

Ваше второе решение довольно уродливое, если можно так выразиться. В частности, мне не нравится использование выражения лямбда для того, что в действительности является объявлением функции. Это не хороший стиль и трудно читать. Другие, похоже, согласны со мной: http://stackoverflow.com/a/134638/1375015 –

+1

Возможно, вы не читали фразу «если мы действительно собираемся в гольф» .... Цель «кодового гольфа» «заключается в создании кратчайшего кода, независимо от его удобочитаемости, и который почти никогда не перестает быть уродливым. – jez

+0

Я не знал об этой фразе. Я все еще не вижу смысла, но в этом контексте, может быть, мой ответ был немного суровым. –

Смежные вопросы