Как разрезать 2D-массив Python? Сбой с: "TypeError: индексы списка должны быть целыми, а не кортежем"

У меня есть 2d-массив в модуле numpy, который выглядит так:

data = array([[1,2,3],
              [4,5,6],
              [7,8,9]])

Я хочу получить фрагмент этого массива, который включает только определенные столбцы элемента. Например, мне могут понадобиться столбцы 0 и 2:

data = [[1,3],
        [4,6],
        [7,9]]

Каков самый питонический способ сделать это? (Нет для циклов, пожалуйста)

Я думал, что это сработает:

newArray = data[:,[0,2]]

но это приводит к:

TypeError: list indices must be integers, not tuple

Ответы

Ответ 1

Ошибка говорит это явно: данные не являются массивом numpy, а списком списков.

попробуйте сначала преобразовать его в массив numpy:

numpy.array(data)[:,[0,2]]

Ответ 2

Если вы хотите разрезать 2D список, следующая функция может помочь

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]]

Ответ 3

Собственно, то, что вы написали, должно работать нормально... Какую версию numpy вы используете?

Просто для проверки, следующее должно отлично работать с любой последней версией numpy:

import numpy as np
x = np.arange(9).reshape((3,3)) + 1
print x[:,[0,2]]

Что для меня дает:

array([[1, 3],
       [4, 6],
       [7, 9]])

как и следовало бы...

Ответ 4

Это может быть не то, что вы ищете, но это будет. zip (* x) [любые столбцы, которые могут вам понадобиться]

Ответ 5

Почему это работает на Numpy, но не на списках Python

Потому что с помощью __getitem__ вы можете запрограммировать классы, чтобы делать все, что хотите, с помощью : и нескольких аргументов.

Numpy делает это, но встроенный list не делает.

Точнее:

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

Затем мы можем открыть объекты среза как:

s = slice(1, 2, 3)
assert s.start == 1
assert s.stop == 2
assert s.step == 3

Итак, когда вы пишете:

[][1, 2]

Python говорит:

TypeError: list indices must be integers, not tuple

потому что вы пытаетесь передать (1, 2) в список __getitem__, а встроенные списки не запрограммированы для обработки аргументов кортежа, только целые числа.

Ответ 6

Остерегайтесь того, что numpy принимает только обычный массив с одинаковым размером для каждого элемента. вы можете как-то использовать: [a[i][0:2] for i in xrange(len(a))] это довольно уродливо, но оно работает.

Ответ 7

newArray = data[:,0:2]

или я что-то не хватает?