If I have an array a, I understand how to slice it in various ways. Specifically, to slice from an arbitrary first index to the end of the array I would do a[2:].
But how would I create a slice object to achieve the same thing? The two ways to create slice objects that are documented are slice(start, stop, step) and slice(stop).
So if I pass a single argument like I would in a[2:] the slice object would interpret it as the stopping index rather than the starting index.
Question: How do I pass an index to the slice object with a starting index and get a slice object that slices all the way to the end? I don't know the total size of the list.
Use None everywhere the syntax-based slice uses a blank value:
someseq[slice(2, None)]
is equivalent to:
someseq[2:]
Similarly, someseq[:10:2] can use a preconstructed slice defined with slice(None, 10, 2), etc.
Related
I'm supposed to create a function that takes a list of elements and return the first and last elements as a new list.
def first_last(lst)
return lst[0, -1]
TypeError: list indices must be integers, not tuple
Why does this not work? I looked at the answer. It's
def first_last(lst):
return [lst[0], lst[-1]]
I don't get it, can someone explain?
In Python, there exists no such list indexing syntax. Just because it makes sense to you does not mean it's valid Python code. Since no such syntax exists for standard Python lists, to Python, it looks like you are trying to use the tuple literal 0, -1 (which is equivalent to (0, -1)) as a single index to your list. Python lists do not support indexing via tuples, therefore the error.
You can do two things with that bracket notation. You can retrieve one element:
return lst[0] # the 0th element of the list
or you can retrieve a continuous slice of elements:
return lst[1:9:2] # a sublist containing every 2nd element from index 1 until 9
# so, incides 1, 3, 5, and 7.
The "solution" here is extracting the 0th element and the last element of the original list, and putting them in a new list. Technically, you could use a list slice to do this, by giving it a "step size" equal to the length of the list minus one:
return lst[::len(lst) - 1]
but that's less clear to look at than the solution you've been given.
Importantly, there are some classes in third-party libraries (e.g. numpy.array) that do let you use array[2, 3] syntax. This is not a base language feature, and it's accomplished by overriding the method that gets called when you use bracket notation to access something on the object, to make it not return an error when you put in the tuple (2, 3). In the case of np.array, it's to make it more familiar to mathematicians - array[2, 3] functions similarly to array[2][3].
I thought Python (numpy) is zero indexing, but when I slice [:0] it returns empty array. I thought I'm saying slice from zero to zero but clearly I am not.
If instead I use A[1] it returns the position 1 element of by zero-indexing.
When using slice it excludes the endpoint, just like in range(a, b) = a..(b-1)
Though when you do list[:1] it should return [list[0]], not an empty array. Thus I suspect that your array is empty from the beginning.
Reference
This question already has answers here:
Array Assignment in numpy / : colon equivalent
(2 answers)
Closed 1 year ago.
I want to slice a multidimensional ndarray but don't know which dimension I will slice on. Lets say we have a ndarray A with shape (6,7,8). Sometimes I need to slice on 1st dimension A[:,3,4], sometimes on third A[1,2,:].
Is there any symbol represent the ":"? I want to use it to generate an index array.
index=np.zeros(3)
index[0]=np.:
index[1]=3
index[2]=4
A[index]
The : slice can be explicitly created by calling slice(None) Here's a short example:
import numpy as np
A = np.arange(9).reshape(3, -1)
# extract the 2nd column
A[:, 1]
# equivalently we can do
cslice = slice(None) # represents the colon
A[cslice, 1]
You want index to be a tuple, with a mix of numbers, lists and slice objects. A number of the numpy functions that take an axis parameter construct such a tuple.
A[(slice(None, None, None), 3, 4)] # == A[:, 3, 4]
there are various ways constructing that tuple:
index = (slice(None),)+(3,4)
index = [slice(None)]*3; index[1] = 3; index[2] = 4
index = np.array([slice(None)]*3]; index[1:]=[3,4]; index=tuple(index)
In this case index can be list or tuple. It just can't be an array.
Starting with a list (or array) is handy in that you can modify values, but it is best to convert it to a tuple before use. I'd have to check the docs for the details, but there are circumstances where a list means something different from a tuple.
http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
Remember that a slicing tuple can always be constructed as obj and used in the x[obj] notation. Slice objects can be used in the construction in place of the [start:stop:step] notation. For example, x[1:10:5,::-1] can also be implemented as obj = (slice(1,10,5), slice(None,None,-1)); x[obj] . This can be useful for constructing generic code that works on arrays of arbitrary dimension.
This is a very simple question but I cannot find documentation anywhere for it. I would like to change the ith element of a list to a slice ("literal colon", like in [:]). Is there any way of doing this?
I have tried doing this:
indexlist = [0] * dim
indexlist[i] = :
This throws a syntax error but I think it gets the point across of what I would like to do.
By a "literal colon" you seem to mean a slice object.
For example:
your_list[i] = slice(None)
To explain what's going on, slicing expressions are actually passed around as tuples of slice objects (or ints, etc).
something[start:stop:step] is equivalent to something[slice(start, stop, step)]. Similarly, something[:] is equivalent to something[slice(None)].
Slicing is implemented through an object's __getitem__ method, so this is also equivalent to something.__getitem__(slice(start, stop, step))
Because you mention numpy in the comments, you might have a look at np.index_exp or np.s_. It lets you quickly create tuples of slices from indexing, and allows you to see what happens.
For example:
import numpy as np
print np.s_[:, 1:5, ::-1, ...]
yields:
(slice(None, None, None), slice(1, 5, None), slice(None, None, -1), Ellipsis)
Which is a tuple of slice objects that you can store and then directly use to slice an object. (e.g. slices = np.s_[0, :, :] and then y = x[slices]).
Now I'm trying to understand possible ways to index numpy structured arrays, and I kinda get stuck with it. Just a couple of simple examples:
import numpy as np
arr = np.array(zip(range(5), range(5, 10)), dtype=[('a', int), ('b', int)])
arr[0] # first row (record)
arr[(0,)] # the same, as expected
arr['a'] # field 'a' of each record
arr[('a',)] # "IndexError: unsupported iterator index" ?!
arr[1:3] # second and third rows (records)
arr[1:3, 'a'] # "ValueError: invalid literal for long() with base 10: 'a'" ?!
arr['a', 1:3] # same error
arr[..., 'a'] # here too...
arr['a', ...] # and here
So, two subquestions arise:
Why is the result for a plain value ('a' in this case) different from the corresponding singleton tuple (('a',))?
Why the last four lines raise the error? And, probably more important, how to get the slice arr['a'][1:3] with a single slice? As you can see, obvious arr['a', 1:3] doesn't work.
I also observed the indexing behavior for built-in list and non-structured ndarray, but couldn't find such issues there: putting a single value in a tuple doesn't change anything, and of course indexing like arr[1, 1:3] for plain ndarray works as expected. Given that, should the errors in my example be considered as bugs in numpy?
First, fields are not the same thing as dimensions - although your array arr has two fields and five rows, numpy actually treats it as one-dimensional (it has shape (5,)). Second, tuples have a special status when used as indices into numpy arrays. When you put a tuple inside the square indexing brackets, numpy interprets it as a sequence of indices into the corresponding dimensions of the array. In the special case where you have nested tuples, each inner tuple is treated as a sequence of indices into that dimension (as if it were a list).
Since fields don't count as dimensions, when you index it with arr[('a',)], numpy interprets 'a' as an index into the rows of arr. The IndexError is therefore raised because strings aren't a valid type for indexing into a dimension of an array (what is the 'a'th row?).
The same thing happens when you try arr['a', 1:3], because this is equivalent to indexing with the tuple ('a', slice(1, 3, None)). The comma between 'a' and 1:3 is what makes it a tuple, regardless of the lack of brackets. Again, numpy tries to index into the rows of arr with 'a', which is invalid. However, even if both elements were valid index types, you would still get an IndexError, since the length of your tuple (2) is greater than the number of dimensions in arr (1).
arr['a'][1:3] and arr[1:3]['a'] are both perfectly valid ways to index a slice of a field.