Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the Python 2D array index order matter when used with colon ( : )

Creating a 2D array such as

x = [range(i, i+10) for i in xrange(1,100,10)]

and indexing using the colon operator like this

>>> x[2][:]
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

works as expected. It returns all of row 2.

However, if I want to retrieve all of column 2, I would instinctively do

>>> x[:][2]

But this also returns

[21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

What is the reasoning behind this? I would intuitively think that this returns the column 2 of each row.

(Also, I am aware I can use numpy to do x[:,2] or I could use list comprehensions to accomplish this, that's not my question)

like image 870
Kyle Avatar asked Jan 21 '15 15:01

Kyle


People also ask

What does colon do in Python indexing?

A colon on the right side of an index means everything after the specified index. A colon on the left side of an index means everything before, but not including, the index.

How do you use a colon in Python?

In Python, a colon is required at the beginning of every block of code. It is easier to explain with an example. Notice how at the end of the if statement I have a colon. This tells Python that the next line of indented code should only be run IF the condition is true.

How does 2D array indexing work?

Two-dimensional (2D) arrays are indexed by two subscripts, one for the row and one for the column. Each element in the 2D array must by the same type, either a primitive type or object type.

What does double colon mean in NumPy?

This means starting from the 3th element from the end, which is number 4, and counting backwards by 2 (skipping 1) until the beginning of the array is reached.


2 Answers

x[2][:] will return the 3rd row of your array, and then return all elements inside that row.

x[:][2] will return all the rows of your array, and then return the 3rd row of them all.

Effectively, they're both the same, x[2][:] == x[:][2].

Printing them in the console it's obvious why this occurs:

In [138]: x[2]
Out[138]: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

In [139]: x[2][:]
Out[139]: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

In [140]: x[:]
Out[140]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
 [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
 [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
 [51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
 [61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
 [71, 72, 73, 74, 75, 76, 77, 78, 79, 80],
 [81, 82, 83, 84, 85, 86, 87, 88, 89, 90],
 [91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]

In [141]: x[:][2]
Out[141]: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

If you wish to get the columns then you can effectively transpose the lists using list(zip(*x)) (added the list in for Py 3). You could then do:

In [3]: list(zip(*x))[2]
Out[3]: (3, 13, 23, 33, 43, 53, 63, 73, 83, 93)

That aside, I'd suggest you use numpy instead for this kind of work.

like image 199
Ffisegydd Avatar answered Oct 15 '22 20:10

Ffisegydd


The reason is that [:] just means "everything", and that the two indexing operations in a row are completely independent.

y = x[2][:]

is

tmp = x[2]
y = tmp[:]  # this only makes a copy, does nothing else

Similarly,

y = x[:][2]

is

tmp = x[:]  # this only makes a copy, does nothing else
y = tmp[2]

in effect both just mean

y = x[2]

There is no 2D indexing going on at any point, Python doesn't have 2D indexing (although numpy has hacks that make it work like there is actual 2D indexing going on).

like image 20
RemcoGerlich Avatar answered Oct 15 '22 20:10

RemcoGerlich