How to slice a 2D Python Array? Fails with: "TypeError: list indices must be integers, not tuple"
I have a 2d array in the numpy module that looks like:
data = array([[1,2,3],
[4,5,6],
[7,8,9]])
I want to get a slice of this array that only includes certain columns of elemen开发者_如何学运维t. For example I may want columns 0 and 2:
data = [[1,3],
[4,6],
[7,9]]
What is the most Pythonic way to do this? (No for loops please)
I thought this would work:
newArray = data[:,[0,2]]
but it results in a:
TypeError: list indices must be integers, not tuple
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]]
Actually, what you wrote should work just fine... What version of numpy are you using?
Just to verify, the following should work perfectly with any recent version of numpy:
import numpy as np
x = np.arange(9).reshape((3,3)) + 1
print x[:,[0,2]]
Which, for me, yields:
array([[1, 3],
[4, 6],
[7, 9]])
as it should...
THis may not be what you are looking for but this is would do. zip(*x)[whatever columns you might need]
Why it works on Numpy but not Python lists
Because with __getitem__
you can program you classes to do whatever you want with :
and multiple arguments.
Numpy does this, but built-in list
s do not.
More precisely:
class C(object):
def __getitem__(self, k):
return k
# Single argument is passed directly.
assert C()[0] == 0
# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)
# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)
# If you omit any part of the slice notation, it becomes None.
assert C()[:] == slice(None, None, None)
assert C()[::] == slice(None, None, None)
assert C()[1::] == slice(1, None, None)
assert C()[:2:] == slice(None, 2, None)
assert C()[::3] == slice(None, None, 3)
# Tuple with a slice object:
assert C()[:, 1] == (slice(None, None, None), 1)
# Ellipsis class object.
assert C()[...] == Ellipsis
We can then open up slice objects as:
s = slice(1, 2, 3)
assert s.start == 1
assert s.stop == 2
assert s.step == 3
So that is why when you write:
[][1, 2]
Python says:
TypeError: list indices must be integers, not tuple
because you are trying to pass (1, 2)
to the list's __getitem__
, and built-in lists are not programmed to deal with tuple arguments, only integers.
Beware that numpy only accept regular array with the same size for each elements.
you can somehow use :
[a[i][0:2] for i in xrange(len(a))]
it's pretty ugly but it works.
newArray = data[:,0:2]
or am I missing something?
The example in question begins with array
, not with np.array
, and array
is not defined as an isolated prefix:
data = array([[1,2,3],
[4,5,6],
[7,8,9]])
data[:,[0,2]]
Error:
NameError: name 'array' is not defined
To reproduce the error, you need to drop that array
frame (without np.
in front, it does not have a definition anyway).
data = [[1,2,3],
[4,5,6],
[7,8,9]]
data[:,[0,2]]
Error:
TypeError: list indices must be integers or slices, not tuple
The user has probably used the inner list of the array for tests but asked the question with a copy from a np.array
output. At least in 2021, the question is just plain wrong: it cannot be reproduced. And I doubt that the behaviour was different in 2010 (numpy is the basic package of python).
For completeness, as in the other answers:
data = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
data[:,[0,2]]
Output:
array([[1, 3],
[4, 6],
[7, 9]])
You do not need a nested list to reproduce this. Slicing a one-dimensional list by two dimensions like with
[1,2][:, 0]
throws the same TypeError: list indices must be integers or slices, not tuple
.
精彩评论