gvsig-3d / 1.10 / trunk / binaries / mac / raster / gdal / GDAL.framework / Versions / 1.7 / Python / site-packages / numpy / doc / structured_arrays.py @ 27
History | View | Annotate | Download (7.04 KB)
1 |
"""
|
---|---|
2 |
=====================================
|
3 |
Structured Arrays (aka Record Arrays)
|
4 |
=====================================
|
5 |
|
6 |
Introduction
|
7 |
============
|
8 |
|
9 |
Numpy provides powerful capabilities to create arrays of structs or records.
|
10 |
These arrays permit one to manipulate the data by the structs or by fields of
|
11 |
the struct. A simple example will show what is meant.: ::
|
12 |
|
13 |
>>> x = np.zeros((2,),dtype=('i4,f4,a10'))
|
14 |
>>> x[:] = [(1,2.,'Hello'),(2,3.,"World")]
|
15 |
>>> x
|
16 |
array([(1, 2.0, 'Hello'), (2, 3.0, 'World')],
|
17 |
dtype=[('f0', '>i4'), ('f1', '>f4'), ('f2', '|S10')])
|
18 |
|
19 |
Here we have created a one-dimensional array of length 2. Each element of
|
20 |
this array is a record that contains three items, a 32-bit integer, a 32-bit
|
21 |
float, and a string of length 10 or less. If we index this array at the second
|
22 |
position we get the second record: ::
|
23 |
|
24 |
>>> x[1]
|
25 |
(2,3.,"World")
|
26 |
|
27 |
Conveniently, one can access any field of the array by indexing using the
|
28 |
string that names that field. In this case the fields have received the
|
29 |
default names 'f0', 'f1' and 'f2'.
|
30 |
|
31 |
>>> y = x['f1']
|
32 |
>>> y
|
33 |
array([ 2., 3.], dtype=float32)
|
34 |
>>> y[:] = 2*y
|
35 |
>>> y
|
36 |
array([ 4., 6.], dtype=float32)
|
37 |
>>> x
|
38 |
array([(1, 4.0, 'Hello'), (2, 6.0, 'World')],
|
39 |
dtype=[('f0', '>i4'), ('f1', '>f4'), ('f2', '|S10')])
|
40 |
|
41 |
In these examples, y is a simple float array consisting of the 2nd field
|
42 |
in the record. But, rather than being a copy of the data in the structured
|
43 |
array, it is a view, i.e., it shares exactly the same memory locations.
|
44 |
Thus, when we updated this array by doubling its values, the structured
|
45 |
array shows the corresponding values as doubled as well. Likewise, if one
|
46 |
changes the record, the field view also changes: ::
|
47 |
|
48 |
>>> x[1] = (-1,-1.,"Master")
|
49 |
>>> x
|
50 |
array([(1, 4.0, 'Hello'), (-1, -1.0, 'Master')],
|
51 |
dtype=[('f0', '>i4'), ('f1', '>f4'), ('f2', '|S10')])
|
52 |
>>> y
|
53 |
array([ 4., -1.], dtype=float32)
|
54 |
|
55 |
Defining Structured Arrays
|
56 |
==========================
|
57 |
|
58 |
One defines a structured array through the dtype object. There are
|
59 |
**several** alternative ways to define the fields of a record. Some of
|
60 |
these variants provide backward compatibility with Numeric, numarray, or
|
61 |
another module, and should not be used except for such purposes. These
|
62 |
will be so noted. One specifies record structure in
|
63 |
one of four alternative ways, using an argument (as supplied to a dtype
|
64 |
function keyword or a dtype object constructor itself). This
|
65 |
argument must be one of the following: 1) string, 2) tuple, 3) list, or
|
66 |
4) dictionary. Each of these is briefly described below.
|
67 |
|
68 |
1) String argument (as used in the above examples).
|
69 |
In this case, the constructor expects a comma-separated list of type
|
70 |
specifiers, optionally with extra shape information.
|
71 |
The type specifiers can take 4 different forms: ::
|
72 |
|
73 |
a) b1, i1, i2, i4, i8, u1, u2, u4, u8, f4, f8, c8, c16, a<n>
|
74 |
(representing bytes, ints, unsigned ints, floats, complex and
|
75 |
fixed length strings of specified byte lengths)
|
76 |
b) int8,...,uint8,...,float32, float64, complex64, complex128
|
77 |
(this time with bit sizes)
|
78 |
c) older Numeric/numarray type specifications (e.g. Float32).
|
79 |
Don't use these in new code!
|
80 |
d) Single character type specifiers (e.g H for unsigned short ints).
|
81 |
Avoid using these unless you must. Details can be found in the
|
82 |
Numpy book
|
83 |
|
84 |
These different styles can be mixed within the same string (but why would you
|
85 |
want to do that?). Furthermore, each type specifier can be prefixed
|
86 |
with a repetition number, or a shape. In these cases an array
|
87 |
element is created, i.e., an array within a record. That array
|
88 |
is still referred to as a single field. An example: ::
|
89 |
|
90 |
>>> x = np.zeros(3, dtype='3int8, float32, (2,3)float64')
|
91 |
>>> x
|
92 |
array([([0, 0, 0], 0.0, [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]),
|
93 |
([0, 0, 0], 0.0, [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]),
|
94 |
([0, 0, 0], 0.0, [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]])],
|
95 |
dtype=[('f0', '|i1', 3), ('f1', '>f4'), ('f2', '>f8', (2, 3))])
|
96 |
|
97 |
By using strings to define the record structure, it precludes being
|
98 |
able to name the fields in the original definition. The names can
|
99 |
be changed as shown later, however.
|
100 |
|
101 |
2) Tuple argument: The only relevant tuple case that applies to record
|
102 |
structures is when a structure is mapped to an existing data type. This
|
103 |
is done by pairing in a tuple, the existing data type with a matching
|
104 |
dtype definition (using any of the variants being described here). As
|
105 |
an example (using a definition using a list, so see 3) for further
|
106 |
details): ::
|
107 |
|
108 |
>>> x = zeros(3, dtype=('i4',[('r','u1'), ('g','u1'), ('b','u1'), ('a','u1')]))
|
109 |
>>> x
|
110 |
array([0, 0, 0])
|
111 |
>>> x['r']
|
112 |
array([0, 0, 0], dtype=uint8)
|
113 |
|
114 |
In this case, an array is produced that looks and acts like a simple int32 array,
|
115 |
but also has definitions for fields that use only one byte of the int32 (a bit
|
116 |
like Fortran equivalencing).
|
117 |
|
118 |
3) List argument: In this case the record structure is defined with a list of
|
119 |
tuples. Each tuple has 2 or 3 elements specifying: 1) The name of the field
|
120 |
('' is permitted), 2) the type of the field, and 3) the shape (optional).
|
121 |
For example:
|
122 |
|
123 |
>>> x = np.zeros(3, dtype=[('x','f4'),('y',np.float32),('value','f4',(2,2))])
|
124 |
>>> x
|
125 |
array([(0.0, 0.0, [[0.0, 0.0], [0.0, 0.0]]),
|
126 |
(0.0, 0.0, [[0.0, 0.0], [0.0, 0.0]]),
|
127 |
(0.0, 0.0, [[0.0, 0.0], [0.0, 0.0]])],
|
128 |
dtype=[('x', '>f4'), ('y', '>f4'), ('value', '>f4', (2, 2))])
|
129 |
|
130 |
4) Dictionary argument: two different forms are permitted. The first consists
|
131 |
of a dictionary with two required keys ('names' and 'formats'), each having an
|
132 |
equal sized list of values. The format list contains any type/shape specifier
|
133 |
allowed in other contexts. The names must be strings. There are two optional
|
134 |
keys: 'offsets' and 'titles'. Each must be a correspondingly matching list to
|
135 |
the required two where offsets contain integer offsets for each field, and
|
136 |
titles are objects containing metadata for each field (these do not have
|
137 |
to be strings), where the value of None is permitted. As an example: ::
|
138 |
|
139 |
>>> x = np.zeros(3, dtype={'names':['col1', 'col2'], 'formats':['i4','f4']})
|
140 |
>>> x
|
141 |
array([(0, 0.0), (0, 0.0), (0, 0.0)],
|
142 |
dtype=[('col1', '>i4'), ('col2', '>f4')])
|
143 |
|
144 |
The other dictionary form permitted is a dictionary of name keys with tuple
|
145 |
values specifying type, offset, and an optional title.
|
146 |
|
147 |
>>> x = np.zeros(3, dtype={'col1':('i1',0,'title 1'), 'col2':('f4',1,'title 2')})
|
148 |
array([(0, 0.0), (0, 0.0), (0, 0.0)],
|
149 |
dtype=[(('title 1', 'col1'), '|i1'), (('title 2', 'col2'), '>f4')])
|
150 |
|
151 |
Accessing and modifying field names
|
152 |
===================================
|
153 |
|
154 |
The field names are an attribute of the dtype object defining the record structure.
|
155 |
For the last example: ::
|
156 |
|
157 |
>>> x.dtype.names
|
158 |
('col1', 'col2')
|
159 |
>>> x.dtype.names = ('x', 'y')
|
160 |
>>> x
|
161 |
array([(0, 0.0), (0, 0.0), (0, 0.0)],
|
162 |
dtype=[(('title 1', 'x'), '|i1'), (('title 2', 'y'), '>f4')])
|
163 |
>>> x.dtype.names = ('x', 'y', 'z') # wrong number of names
|
164 |
<type 'exceptions.ValueError'>: must replace all names at once with a sequence of length 2
|
165 |
|
166 |
Accessing field titles
|
167 |
====================================
|
168 |
|
169 |
The field titles provide a standard place to put associated info for fields.
|
170 |
They do not have to be strings.
|
171 |
|
172 |
>>> x.dtype.fields['x'][2]
|
173 |
'title 1'
|
174 |
|
175 |
"""
|