2

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

xy = np.random.random_integers(0,10,size=(N,2)) 

Лишних списка [... преобразования необходимо для преобразования для того, чтобы работать в Python 3.4, это не обязательно, но не вредно при использовании Python 2.7.

следующие работы:

>>> # attempts to formulate [id,(x,y)] with specified dtype 
>>> N = 10 
>>> x = np.random.random_integers(0,10,size=N) 
>>> y = np.random.random_integers(0,10,size=N) 
>>> id = np.arange(N) 
>>> dt = np.dtype([('ID','<i4'),('Shape',('<f8',(2,)))]) 
>>> arr = np.array(list(zip(id,np.hstack((x,y)))),dt) 
>>> arr 
    array([(0, [7.0, 7.0]), (1, [7.0, 7.0]), (2, [5.0, 5.0]), (3, [0.0, 0.0]), 
      (4, [6.0, 6.0]), (5, [6.0, 6.0]), (6, [7.0, 7.0]), 
      (7, [10.0, 10.0]), (8, [3.0, 3.0]), (9, [7.0, 7.0])], 
      dtype=[('ID', '<i4'), ('Shape', '<f8', (2,))]) 

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

>>> a = np.vstack((id,x,y)).T 
>>> a 
array([[ 0, 7, 6], 
     [ 1, 7, 7], 
     [ 2, 5, 9], 
     [ 3, 0, 1],  
     [ 4, 6, 1], 
     [ 5, 6, 6], 
     [ 6, 7, 6], 
     [ 7, 10, 9], 
     [ 8, 3, 2], 
     [ 9, 7, 8]]) 

Я попробовал несколько способов пытается переформулировать выше массив, так что мой DTYPE будет работать, и я просто не могу понять это (это включало vstacking vstack и т.д.) , Поэтому мой вопрос ... как я могу использовать версию vstack и получить ее в формате, соответствующем моим требованиям dtype, без необходимости проходить процедуру, которую я сделал. Я надеюсь, что это очевидно, но я нарезанный, сложены и эллипсированы в бесконечный цикл.

РЕЗЮМЕ

Большое спасибо hpaulj. Я включил два воплощения, основанные на его предложениях для других. Решение pure numpy значительно быстрее и намного чище.

""" 
Script: pnts_StackExch 
Author: [email protected] 
Modified: 2015-08-24 
Purpose: 
    To provide some timing options on point creation in preparation for 
    point-to-point distance calculations using einsum. 
Reference: 
    http://stackoverflow.com/questions/32224220/ 
    methods-of-creating-a-structured-array 
Functions: 
    decorators: profile_func, timing, arg_deco 
    main: make_pnts, einsum_0 
""" 
import numpy as np 
import random 
import time 
from functools import wraps 

np.set_printoptions(edgeitems=5,linewidth=75,precision=2,suppress=True,threshold=5) 

# .... wrapper funcs ............. 
def delta_time(func): 
    """timing decorator function""" 
    import time 
    @wraps(func) 
    def wrapper(*args, **kwargs): 
     print("\nTiming function for... {}".format(func.__name__)) 
     t0 = time.time()    # start time 
     result = func(*args, **kwargs) # ... run the function ... 
     t1 = time.time()    # end time 
     print("Results for... {}".format(func.__name__)) 
     print(" time taken ...{:12.9f} sec.".format(t1-t0)) 
     #print("\n print results inside wrapper or use <return> ... ") 
     return result     # return the result of the function 
    return wrapper 

def arg_deco(func): 
    """This wrapper just prints some basic function information.""" 
    @wraps(func) 
    def wrapper(*args,**kwargs): 
     print("Function... {}".format(func.__name__)) 
     #print("File....... {}".format(func.__code__.co_filename)) 
     print(" args.... {}\n kwargs. {}".format(args,kwargs)) 
     #print(" docs.... {}\n".format(func.__doc__)) 
     return func(*args, **kwargs) 
    return wrapper 

# .... main funcs ................ 
@delta_time 
@arg_deco 
def pnts_IdShape(N=1000000,x_min=0,x_max=10,y_min=0,y_max=10): 
    """Make N points based upon a random normal distribution, 
     with optional min/max values for Xs and Ys 
    """ 
    dt = np.dtype([('ID','<i4'),('Shape',('<f8',(2,)))]) 
    IDs = np.arange(0,N) 
    Xs = np.random.random_integers(x_min,x_max,size=N) # note below 
    Ys = np.random.random_integers(y_min,y_max,size=N) 
    a = np.array([(i,j) for i,j in zip(IDs,np.column_stack((Xs,Ys)))],dt) 
    return IDs,Xs,Ys,a 

@delta_time 
@arg_deco 
def alternate(N=1000000,x_min=0,x_max=10,y_min=0,y_max=10): 
    """ after hpaulj and his mods to the above and this. See docs 
    """ 
    dt = np.dtype([('ID','<i4'),('Shape',('<f8',(2,)))]) 
    IDs = np.arange(0,N) 
    Xs = np.random.random_integers(0,10,size=N) 
    Ys = np.random.random_integers(0,10,size=N) 
    c_stack = np.column_stack((IDs,Xs,Ys)) 
    a = np.ones(N, dtype=dt) 
    a['ID'] = c_stack[:,0] 
    a['Shape'] = c_stack[:,1:] 
    return IDs,Xs,Ys,a 

if __name__=="__main__": 
    """time testing for various methods 
    """ 
    id_1,xs_1,ys_1,a_1 = pnts_IdShape(N=1000000,x_min=0, x_max=10, y_min=0, y_max=10) 
    id_2,xs_2,ys_2,a_2 = alternate(N=1000000,x_min=0, x_max=10, y_min=0, y_max=10) 

результатов синхронизации для 1000000 точек являются

Timing function for... pnts_IdShape 
Function... **pnts_IdShape** 
    args....() 
    kwargs. {'N': 1000000, 'y_max': 10, 'x_min': 0, 'x_max': 10, 'y_min': 0} 
Results for... pnts_IdShape 
    time taken ... **0.680652857 sec**. 

Timing function for... **alternate** 
Function... alternate 
    args....() 
    kwargs. {'N': 1000000, 'y_max': 10, 'x_min': 0, 'x_max': 10, 'y_min': 0} 
Results for... alternate 
    time taken ... **0.060056925 sec**. 
+0

Вы используете один способ положить значения в structured array - список кортежей. Другой инициализирует его, а затем заполняет поле по полю. С 2 полями, которые должны быть быстрыми. Когда поля неравномерны по длине, это единственные 2 варианта. – hpaulj

+0

@hpaulj не уверен, что я следую, поля однородны по длине ... если вы имеете в виду количество строк. Я просто пытаюсь понять, как изменить форму массива так, чтобы столбец id оставался, но «shape» является результатом объединения столбцов x и y. Я могу сделать это с помощью hstack или zip, чтобы получить x, y вместе, но потом мне нужно снова застегнуть молнию, чтобы объединить id с «формой». Я не могу применить dtype к массиву 3 столбцов, очевидно, поскольку он не в правильной форме ... что я пытаюсь сделать, [[id, (x, y)], ... [ idn, (xn, yn)]] –

+0

Заполните поле id' в одном сообщении. Тогда другой. – hpaulj

ответ

1

Есть 2 способа заполнения структурированного массива (http://docs.scipy.org/doc/numpy/user/basics.rec.html#filling-structured-arrays) - по строке (или строки с списком кортежей), а также с помощью поля.

Чтобы сделать это поле, создайте пустой структурированный массив и присвоить значения по имени

In [19]: a=np.column_stack((id,x,y)) 
# same as your vstack().T 

In [20]: Y=np.zeros(a.shape[0], dtype=dt) 
# empty, ones, etc 
In [21]: Y['ID'] = a[:,0] 
In [22]: Y['Shape'] = a[:,1:] 
# (2,) field takes a 2 column array 
In [23]: Y 
Out[23]: 
array([(0, [8.0, 8.0]), (1, [8.0, 0.0]), (2, [6.0, 2.0]), (3, [8.0, 8.0]), 
     (4, [3.0, 2.0]), (5, [6.0, 1.0]), (6, [5.0, 6.0]), (7, [7.0, 7.0]), 
     (8, [6.0, 1.0]), (9, [6.0, 6.0])], 
     dtype=[('ID', '<i4'), ('Shape', '<f8', (2,))]) 

поля на поверхности

arr = np.array(list(zip(id,np.hstack((x,y)))),dt) 

выглядит как ОК способ построения списка кортежей необходимо заполнить массив. Но результат дублирует значения x вместо y. Мне нужно посмотреть, что не так.

Вы можете получить представление о массиве, таком как a, если dtype совместим - буфер данных для 3 столбцов int выстроен так же, как один с 3 полями int.

a.view('i4,i4,i4') 

Но ваш DTYPE хочет 'i4, f8, f8', смесь 4-х и 8-байтовых полей, а также сочетание междунар и поплавком. Для этого необходимо преобразовать буфер a. view не может этого сделать. (даже не спрашивайте о .astype.)


исправленный список метода кортежей:

In [35]: np.array([(i,j) for i,j in zip(id,np.column_stack((x,y)))],dt) 
Out[35]: 
array([(0, [8.0, 8.0]), (1, [8.0, 0.0]), (2, [6.0, 2.0]), (3, [8.0, 8.0]), 
     (4, [3.0, 2.0]), (5, [6.0, 1.0]), (6, [5.0, 6.0]), (7, [7.0, 7.0]), 
     (8, [6.0, 1.0]), (9, [6.0, 6.0])], 
     dtype=[('ID', '<i4'), ('Shape', '<f8', (2,))]) 

В списке понимание создает список, как:

[(0, array([8, 8])), 
(1, array([8, 0])), 
(2, array([6, 2])), 
....] 

Для каждого кортежа в списке, то [0] идет в первом поле dtype и [1] (малый массив), идет во 2-й.

кортежей также может быть построен с

[(i,[j,k]) for i,j,k in zip(id,x,y)] 

dt1 = np.dtype([('ID','<i4'),('Shape',('<i4',(2,)))]) 

вид совместимый DTYPE (еще 3 числа)

In [42]: a.view(dtype=dt1) 
Out[42]: 
array([[(0, [8, 8])], 
     [(1, [8, 0])], 
     [(2, [6, 2])], 
     [(3, [8, 8])], 
     [(4, [3, 2])], 
     [(5, [6, 1])], 
     [(6, [5, 6])], 
     [(7, [7, 7])], 
     [(8, [6, 1])], 
     [(9, [6, 6])]], 
     dtype=[('ID', '<i4'), ('Shape', '<i4', (2,))]) 
+0

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

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