If you restrict yourself to the Python standard library, then a list of lists is the closest construct:
arr = [[1,2],[3,4]]
gives a 2d-like array. The rows can be accessed as arr[i] for i in {0,..,len(arr}, but column access is difficult.
If you are willing to add a library dependency, the NumPy package is what you really want. You can create a fixed-length array from a list of lists using:
import numpy
arr = numpy.array([[1,2],[3,4]])
Column access is the same as for the list-of-lists, but column access is easy: arr[:,i] for i in {0,..,arr.shape[1]} (the number of columns).
In fact NumPy arrays can be n-dimensional.
Empty arrays can be created with
numpy.empty(shape)
where shape is a tuple of size in each dimension; shape=(1,3,2) gives a 3-d array with size 1 in the first dimension, size 3 in the second dimension and 2 in the 3rd dimension.
If you want to store objects in a NumPy array, you can do that as well:
arr = numpy.empty((1,), dtype=numpy.object)
arr[0] = 'abc'
For more info on the NumPy project, check out the NumPy homepage.
To create a standard python array of arrays of arbitrary size:
a = [[0]*cols for _ in [0]*rows]
It is accessed like this:
a[0][1] = 5 # set cell at row 0, col 1 to 5
A small python gotcha that's worth mentioning: It is tempting to just type
a = [[0]*cols]*rows
but that'll copy the same column array to each row, resulting in unwanted behaviour. Namely:
>>> a[0][0] = 5
>>> print a[1][0]
5
This works:
a = [[1, 2, 3], [4, 5, 6]]
nd_a = np.array(a)
So this should work too:
nd_a = np.array([[x for x in y] for y in a])
To create a new array, it seems numpy.zeros is the way to go
import numpy as np
a = np.zeros(shape=(x, y))
You can also set a datatype to allocate it sensibly
>>> np.zeros(shape=(5,2), dtype=np.uint8)
array([[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0]], dtype=uint8)
>>> np.zeros(shape=(5,2), dtype="datetime64[ns]")
array([['1970-01-01T00:00:00.000000000', '1970-01-01T00:00:00.000000000'],
['1970-01-01T00:00:00.000000000', '1970-01-01T00:00:00.000000000'],
['1970-01-01T00:00:00.000000000', '1970-01-01T00:00:00.000000000'],
['1970-01-01T00:00:00.000000000', '1970-01-01T00:00:00.000000000'],
['1970-01-01T00:00:00.000000000', '1970-01-01T00:00:00.000000000']],
dtype='datetime64[ns]')
See also
- How do I create an empty array/matrix in NumPy?
- np.full(size, 0) vs. np.zeros(size) vs. np.empty()
If your number of ranges is not too large you can create them by hand
gm09 = xdata >= -0.9
gm06 = xdata >= -0.6
g0 = xdata >= 0
ranges = [xdata[gm09 & ~gm06], xdata[gm06 & ~g0]]
result = [f(r) for r in ranges]
where f is your scipy function.
If your number of ranges is large, you can sort your data and then use
searchsorted. Assuming you have the boundaries of blocks in the sorted array bnd:
xs = np.sort(xdata)
xbnd = np.searchsorted(xs, bnd)
ranges = [xs[l:r] for l, r in zip(xbnd[:-1], xbnd[1:])]
result = [f(r) for r in ranges]
Note that this differs from the first solution in that your ranges will be sorted.
If you need to preserve the original order you can use indirect sorting
order = np.argsort(xdata)
xbnd = np.searchsorted(xdata[order], bnd)
ordord = [np.sort(order[l:r]) for l, r in zip(xbnd[:-1], xbnd[1:])]
ranges = [xdata[oo] for oo in ordord]
result = [f(r) for r in ranges]
multidimensional arrays must be rectangular, so if not all of your rows/columns have the same length you're out of luck.
However there are ways to deal with this. One way would be to create a list of arrays:
>>> arr = np.random.random((10)) # using this for values
>>> # each item in ranges corresponds to the lower and upper border.
>>> ranges = [(0, 0.3), (0.3, 0.6), (0.6, 1)]
>>> [arr[(arr >= lower) & (arr < upper)] for lower, upper in ranges]
[array([ 0.15346374]),
array([ 0.38144735, 0.45017858, 0.52710788, 0.36339812]),
array([ 0.79770651, 0.77543868, 0.94824291, 0.87412998, 0.70890894])]
That's not a multidimensional array, just a list of arrays, but depending on your needs that may be enough.
Note that to leverage the full power of numpy, you'd be much better off with a 3-dimensional numpy array. Breaking apart the 3-d array into a 2-d array with 1-d values may complicate your code and force you to use loops instead of built-in numpy functions.
It may be worth investing the time to refactor your code to use the superior 3-d numpy arrays.
However, if that's not an option, then:
import numpy as np
storageMatrix=np.empty((4,9),dtype='object')
By setting the dtype to 'object', we are telling numpy to allow each element of storageMatrix to be an arbitrary Python object.
Now you must initialize each element of the numpy array to be an 1-d numpy array:
storageMatrix[column,row]=np.arange(4096)
And then you can access the array elements like this:
storageMatrix[column,row][0] = 1
storageMatrix[column,row][4092] = 2
The Tentative NumPy Tutorial says you can declare a 2D array using the comma operator:
x = ones( (3,4) )
and index into a 2D array like this:
>>> x[1,2] = 20
>>> x[1,:] # x's second row
array([ 1, 1, 20, 1])
>>> x[0] = a # change first row of x
>>> x
array([[10, 20, -7, -3],
[ 1, 1, 20, 1],
[ 1, 1, 1, 1]])