2016-05-06 4 views
4

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

names = list(a.dtype.names) 
if name_to_remove in names: 
    names.remove(name_to_remove) 
a = a[names] 

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

Есть ли хороший способ сделать это?

+0

Если вы хотите избежать использования списка «имена», вы можете написать функцию лямбда, которая выполняет эту операцию. –

+0

Проблема в том, что 'a [names]' создает копию исходного массива, присваивает ее a и только затем удаляет исходный массив. Я хочу избежать этой копии. Может быть, я должен как-то прояснить свой вопрос? –

+0

Вы говорите о создании списка «имен»? –

ответ

5

Вы можете создать новый тип данных, содержащий только поля, которые вы хотите, с теми же смещениями поля и теми же параметрами, что и тип данных исходного массива, а затем использовать этот новый тип данных для создания представления исходного массива , Функция dtype обрабатывает аргументы со многими форматами; соответствующий раздел описан в разделе документации под названием "Specifying and constructing data types". Прокрутите вниз до подраздела, начинающегося с

{'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...} 

Вот пара удобных функций, которые используют эту идею.

import numpy as np 


def view_fields(a, names): 
    """ 
    `a` must be a numpy structured array. 
    `names` is the collection of field names to keep. 

    Returns a view of the array `a` (not a copy). 
    """ 
    dt = a.dtype 
    formats = [dt.fields[name][0] for name in names] 
    offsets = [dt.fields[name][1] for name in names] 
    itemsize = a.dtype.itemsize 
    newdt = np.dtype(dict(names=names, 
          formats=formats, 
          offsets=offsets, 
          itemsize=itemsize)) 
    b = a.view(newdt) 
    return b 


def remove_fields(a, names): 
    """ 
    `a` must be a numpy structured array. 
    `names` is the collection of field names to remove. 

    Returns a view of the array `a` (not a copy). 
    """ 
    dt = a.dtype 
    keep_names = [name for name in dt.names if name not in names] 
    return view_fields(a, keep_names) 

Например,

In [297]: a 
Out[297]: 
array([(10.0, 13.5, 1248, -2), (20.0, 0.0, 0, 0), (30.0, 0.0, 0, 0), 
     (40.0, 0.0, 0, 0), (50.0, 0.0, 0, 999)], 
     dtype=[('x', '<f8'), ('y', '<f8'), ('i', '<i8'), ('j', '<i8')]) 

In [298]: b = remove_fields(a, ['i', 'j']) 

In [299]: b 
Out[299]: 
array([(10.0, 13.5), (20.0, 0.0), (30.0, 0.0), (40.0, 0.0), (50.0, 0.0)], 
     dtype={'names':['x','y'], 'formats':['<f8','<f8'], 'offsets':[0,8], 'itemsize':32}) 

Убедитесь, что b вид (не копия) a путем изменения b[0]['x'] ...

In [300]: b[0]['x'] = 3.14 

и видя, что a также изменяется :

In [301]: a[0] 
Out[301]: (3.14, 13.5, 1248, -2) 
Смежные вопросы