7

I have a numpy array like this:

candidates = 

array([[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
        0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
        0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1],
       [1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
        0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0]])

And I do not understand what is the difference between candidates[0]:

candidates[0] = 

array([1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
       0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]

candidates[0].shape = (34,)

And candidates[0:1]:

candidates[0:1] = 

array([[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
        0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]])

candidates[0:1].shape = (1, 34)

because I believe the two should give the exact same results? I mean the later i.e. candidates[0:1] is supposed to represent the first element only, right? So, what is the difference between the two exactly?

RezAm
  • 548
  • 2
  • 6
  • 20
  • 4
    The is the same as normal Python slicing: `candidates[0]` is the first element (in this case, the first row); `candidates[0:1]` is a collection of the first one elements (in this case, a 2D array containing only the first row). That's why the shapes are different. Compare `lst = [1,2,3]` then `lst[0]` vs. `lst[0:1]`: one is `1`, the other is `[1]`. – abarnert May 05 '18 at 23:03
  • Hi. The question has already been discussed https://stackoverflow.com/questions/42882842/whats-the-difference-between-n-and-n-1-in-numpy – decadenza May 05 '18 at 23:06
  • @decadenza I'm not sure whether it's a dup or not, because I'm not sure whether the OP is unclear about why `[0]` and `[0:1]` return different shapes, or about why `(34,)` and `(1,34)` are different shapes. The linked question answers only the latter. – abarnert May 05 '18 at 23:09
  • @decadenza (Also, the question you linked is itself closed as a dup of [this one](https://stackoverflow.com/questions/22053050/), which I think has an even better answer—but fortunately, if we want to close it, we can link both.) – abarnert May 05 '18 at 23:12
  • @abarnert thanks for your response! I obv know the difference between `[0]` and `[0:1]`. I just needed to understand that the later results in a 2D array. Idk maybe I should remove the word 'size' from the question to avoid confusion? Or if you think you can improve my wording pls go ahead as English is not my first language haha. Thank you! – RezAm May 05 '18 at 23:21
  • @Antonio So do the other answers solve your question, because it's the shape `(1, 34)` that confused you, or is it the fact that `[0:1]` returns a 2D array that confused you? – abarnert May 05 '18 at 23:25
  • @abarnert no the answers to those questions are unrelated to my confusion. I just did not understand that [0] is indexing but [0:1] is slicing and leads to a 2D array. I removed the word 'size' from my question btw. Pls feel free to make it better if you will. Thanks! – RezAm May 05 '18 at 23:29
  • https://docs.scipy.org/doc/numpy-1.14.0/user/basics.indexing.html#single-element-indexing and the following section explain `single element indexing` and `slicing`. – hpaulj May 06 '18 at 00:05

3 Answers3

10

In Python, [0] is indexing—it returns the first element, while [0:1] is slicing—it returns a collection of all of the first 1 elements.

This may be easier to see with a plain old list:

>>> lst = [1, 2, 3]
>>> lst[0]
1
>>> lst[0:1]
[1]

Numpy extends Python indexing and slicing, and some of these would give you a 2D result, for different reasons—e.g., you could index with [0] as an “array-like”, which would work as an index array), but the relevant basics are the same here. For a 2D numpy array, the elements are rows, so candidates[0] is the first row—a 1D array, while candidates[0:1] is an array of all of the first 1 rows—a 2D array. So the first one has shape (34,), and the second has shape (1, 34).

The difference may not be obvious if you don't look closely, but compare how the two start:

array([1,
array([[1,

They're not lined up, because the second one has two brackets instead of one, which is because it's a 2D array instead of 1D.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 1
    @jpp Actually, it’s not slicing, it’s indexing with an array-like. And I think getting into all the different ways numpy extends indexing (and slicing) is probably over complicating things. – abarnert May 05 '18 at 23:48
  • 1
    @jpp Although maybe it’s at least worth adding a bit more to the phrase “Numpy extends indexing and slicing a bit”, to include one example? – abarnert May 05 '18 at 23:49
  • Yep - that might help. Not sure the best way to phrase it. – jpp May 05 '18 at 23:55
2

The difference is the number of dimensions: candidates[0:1] will return a 2 dimensional array, whereas candidates[0] will return a 1 dimensional array:

>>> candidates[0:1].ndim
2
>>> candidates[0].ndim
1

You can also kind of "see" the dimensionality by the output of candidates[0:1]: notice the number of square brackets around the array? These can be a hint at the dimensionality of an array

sacuL
  • 49,704
  • 8
  • 81
  • 106
2

No. The difference is the shape of your array. In the first instance, you have an array in 1 dimension. In the second, you have an array in 2 dimensions.

You can test by testing the shape property of your arrays:

print(np.array([[1, 0]]).shape)
(1, 2)

print(np.array([1, 0]).shape)
(2,)

By slicing you array with a list of items, e.g. [0:1], your result will have an added dimension. Note this has nothing to do with using a range; it is also true when you use a list with 1 element as an indexer:

x = np.array([[0, 1], [2, 3]])

print(x[[0]].shape)
# (1, 2)
jpp
  • 159,742
  • 34
  • 281
  • 339