For the first question:
A = [ [1,2,3,4,5,6,7,8] for i in range(8)]
n = len(A[0])
x = int(n/2)
TEMP = [[None]*2 for i in range(2)]
for w in range(2):
for q in range(2):
TEMP[w][q] = [item[q * x:(q * x) + x] for item in A[w * x:(w * x) + x]]
for w in range(2):
for q in range(2):
print("{i}, {j}: {item}".format(i=w, j=q, item=repr(TEMP[w][q])))
Answer from Salah Eddine Lahniche on Stack OverflowFor the first question:
A = [ [1,2,3,4,5,6,7,8] for i in range(8)]
n = len(A[0])
x = int(n/2)
TEMP = [[None]*2 for i in range(2)]
for w in range(2):
for q in range(2):
TEMP[w][q] = [item[q * x:(q * x) + x] for item in A[w * x:(w * x) + x]]
for w in range(2):
for q in range(2):
print("{i}, {j}: {item}".format(i=w, j=q, item=repr(TEMP[w][q])))
Numpy makes the vertical slicing of 2 dimensional array easier. However, you can achieve the same results without it. Imagine if we have the following 2D list:
arr1=[[1,1,1,0,0,0],[0,1,0,0,0,0],[1,1,1,0,0,0],[0,0,2,4,4,0],[0,0,0,2,0,0],[0,0,1,2,4,0]]
which is represented as the following matrix:
[[1, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0],
[0, 0, 2, 4, 4, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 1, 2, 4, 0]]
Let's say that you want to slice this to form the pattern below :

This can be achieved without numpy by the following :
for x in range (0,4):
for y in range (0,4):
# Here we traverse through the 2D array vertically
temp_matrix= arr1[x][y:y+3],arr1[x+1][y:y+3],arr1[x+2][y:y+3]
print (temp_matrix)
If we use numpy instead we can re-write the following code :
arr=np.array(arr1)
rows = arr.shape[0]
cols = arr.shape[1]
for x in range (0,rows-2):
for y in range (0, cols-2):
print(arr[x:x+3,y:y+3])
Videos
If you use numpy, this is easy:
slice = arr[:2,:2]
or if you want the 0's,
slice = arr[0:2,0:2]
You'll get the same result.
*note that slice is actually the name of a builtin-type. Generally, I would advise giving your object a different "name".
Another way, if you're working with lists of lists*:
slice = [arr[i][0:2] for i in range(0,2)]
(Note that the 0's here are unnecessary: [arr[i][:2] for i in range(2)] would also work.).
What I did here is that I take each desired row 1 at a time (arr[i]). I then slice the columns I want out of that row and add it to the list that I'm building.
If you naively try: arr[0:2] You get the first 2 rows which if you then slice again arr[0:2][0:2], you're just slicing the first two rows over again.
*This actually works for numpy arrays too, but it will be slow compared to the "native" solution I posted above.
To slice a multi-dimensional array, the dimension (i.e. axis) must be specified. As OP noted, arr[i:j][i:j] is exactly the same as arr[i:j] because arr[i:j] sliced along the first axis (rows) and has the same number of dimensions as arr (you can confirm by arr[i:j].ndim == arr.ndim); so the second slice is still slicing along the first dimension (which was already done by the first slice). To slice along the second dimension, it must be explicitly specified, e.g.:
arr[:2][:, :2] # its output is the same as `arr[:2, :2]`
A bare : means slice everything in that axis, so there's an implicit : for the second axis in the above code (i.e. arr[:2, :][:, :2]). What the above code is doing is slicing the first two rows (or first two arrays along the first axis) and then slice the first two columns (or the first two arrays along the second axis) from the resulting array.
An ... can be used instead of multiple colons (:), so for a general n-dimensional array, the following produce the same output:
w = arr[i:j, m:n]
x = arr[i:j, m:n, ...]
y = arr[i:j][:, m:n]
z = arr[i:j, ...][:, m:n, ...]
That said, arr[:2, :2] is the canonical way because in the case of arr[i:j][:, i:j], arr[i:j] creates a temporary array which is indexed by [:, i:j], so it's comparatively inefficient.
However, there are cases where chained indexing makes sense (or readable), e.g., if you want to index a multi-dimensional array using a list of indices. For example, if you want to slice the top-left quarter of a 4x4 array using a list of indices, then chained indexing gives the correct result whereas a single indexing gives a different result (it's because of numpy advanced indexing) where the values correspond to the index pair for each position in the index lists.
arr = np.arange(1,17).reshape(4,4)
rows = cols = [0,1]
arr[rows][:, cols] # <--- correct output
arr[rows, cols] # <--- wrong output
arr[[[e] for e in rows], cols] # <--- correct output
arr[np.ix_(rows, cols)] # <--- correct output
The error say it explicitely : data is not a numpy array but a list of lists.
try to convert it to an numpy array first :
numpy.array(data)[:,[0,2]]
If you'd want to slice 2D list the following function may help
def get_2d_list_slice(self, matrix, start_row, end_row, start_col, end_col):
return [row[start_col:end_col] for row in matrix[start_row:end_row]]
Hi, I'm trying to create a simple game of life and I have problems putting zeros on the edge of my grid. When i try the following code i get an error and I don't understand why.
the variable grid represent a 2D array.
the code:
grid[0,:] = np.zeros_like(grid[0,:])#top_row
grid[-1,:] = np.zeros_like(grid[-1,:])#bottom_row
grid[:,0] = np.zeros_like(grid[:,0])#left
grid[:,-1] = np.zeros_like(grid[:,-1])#right
the error:
TypeError: list indices must be integers or slices, not tuple
So obviously, I would like to avoid the first solution, especially since this will be running for sizes up to 100k. However, I also do not want to use too many dependencies.
You must choose which of these is more important to you. Numpy has better performance precisely because it doesn't use the builtin Python types and uses its own types that are optimized for numerical work. If your data are going to be numeric and you're going to have 100k rows/columns, you will see a gigantic performance increase with numpy. If you want to avoid the numpy dependency, you will have to live with reduced performance. (Obviously you can always write your own Python libraries or C extensions to optimize for your particular use case, but these will then be dependencies like any other.)
Personally I would recommend you just use numpy. It is so widely used that anyone who is considering using a library that deals with 100k multidimensional arrays probably already has numpy installed.
I tried a couple of alternatives;
Edit: The original eArray was faulty, it created references to the same list...
Edit2: Added array.array as suggested by Sebastian.
import time
import numpy as np
import array
t1 = 0
def starttimer():
global t1
t1 = time.clock()
def stoptimer(s):
t2 = time.clock()
print 'elapsed time for "{}": {:.3f} seconds'.format(s, t2-t1)
def cArray(size):
c = [[0. for i in range(size)] for j in range(size)]
return c
def dArray(size):
d = [[0. for i in xrange(size)] for j in xrange(size)]
return d
def eArray2(size):
return [[0.]*size for j in xrange(size)]
def fArray(size):
return np.zeros((size,size))
def gArray(size):
return [array.array('d', [0])*size for j in xrange(size)]
sz = 5000
starttimer()
cArray(sz)
stoptimer('cArray')
starttimer()
dArray(sz)
stoptimer('dArray')
starttimer()
fArray(sz)
stoptimer('fArray')
starttimer()
gArray(sz)
stoptimer('gArray')
The results (cpython 2.7.3 on FreeBSD amd64, if anyone cares):
> python tmp/test.py
elapsed time for "cArray": 2.312 seconds
elapsed time for "dArray": 1.945 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.695 seconds
> python tmp/test.py
elapsed time for "cArray": 2.312 seconds
elapsed time for "dArray": 1.914 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.695 seconds
> python tmp/test.py
elapsed time for "cArray": 2.328 seconds
elapsed time for "dArray": 1.906 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.703 seconds
So,here I come again ๐คฃ
I don't get slicing in 2D..
In my lesson,I was taught that using this
d[1:2,1]
means the 2nd element from the last two rows,and 2nd element from 1st column should be sliced..but when I use it I get only one element.Did I do something wrong?Can some of you awesome people hook me up with an explanation?
Here's some code for your palates:
a=[[1,2,3],[4,5,6],[7,8,9]] import numpy as np d=np.array(a) d[1:2,1]
To answer this question, we have to look at how indexing a multidimensional array works in Numpy. Let's first say you have the array x from your question. The buffer assigned to x will contain 16 ascending integers from 0 to 15. If you access one element, say x[i,j], NumPy has to figure out the memory location of this element relative to the beginning of the buffer. This is done by calculating in effect i*x.shape[1]+j (and multiplying with the size of an int to get an actual memory offset).
If you extract a subarray by basic slicing like y = x[0:2,0:2], the resulting object will share the underlying buffer with x. But what happens if you acces y[i,j]? NumPy can't use i*y.shape[1]+j to calculate the offset into the array, because the data belonging to y is not consecutive in memory.
NumPy solves this problem by introducing strides. When calculating the memory offset for accessing x[i,j], what is actually calculated is i*x.strides[0]+j*x.strides[1] (and this already includes the factor for the size of an int):
x.strides
(16, 4)
When y is extracted like above, NumPy does not create a new buffer, but it does create a new array object referencing the same buffer (otherwise y would just be equal to x.) The new array object will have a different shape then x and maybe a different starting offset into the buffer, but will share the strides with x (in this case at least):
y.shape
(2,2)
y.strides
(16, 4)
This way, computing the memory offset for y[i,j] will yield the correct result.
But what should NumPy do for something like z=x[[1,3]]? The strides mechanism won't allow correct indexing if the original buffer is used for z. NumPy theoretically could add some more sophisticated mechanism than the strides, but this would make element access relatively expensive, somehow defying the whole idea of an array. In addition, a view wouldn't be a really lightweight object anymore.
This is covered in depth in the NumPy documentation on indexing.
Oh, and nearly forgot about your actual question: Here is how to make the indexing with multiple lists work as expected:
x[[[1],[3]],[1,3]]
This is because the index arrays are broadcasted to a common shape. Of course, for this particular example, you can also make do with basic slicing:
x[1::2, 1::2]
As Sven mentioned, x[[[0],[2]],[1,3]] will give back the 0 and 2 rows that match with the 1 and 3 columns while x[[0,2],[1,3]] will return the values x[0,1] and x[2,3] in an array.
There is a helpful function for doing the first example I gave, numpy.ix_. You can do the same thing as my first example with x[numpy.ix_([0,2],[1,3])]. This can save you from having to enter in all of those extra brackets.