Отрицательное индексирование R в Python. Не принимайте кусочки

Головка программирования My R подключена для использования отрицательных индексов резки для исключения элементов.

В качестве примера:

my_list = [0,1,2,3,4,5,6,7,8,9]
my_neg_slice = [-2, -8, 0, -5]

Вернет

[1 3 4 6 7 9]

то есть. вернуть все индексы не в (0, 2, 5, 8).

Это больше вопрос, удовлетворяющий мое любопытство, поскольку отрицательное индексирование Pythonic для меня совершенно новое (это не критика реализации Python, поскольку мне это очень нравится). Кто-нибудь реализовал R_Style_Negative_Indexing в Python? Я очень новичок в Python, поэтому этот тип индексирования может уже существовать? Возможно, кто-то создал пользовательское расширение (извините, если это не правильная терминология), чтобы расширить соответствующую библиотеку?

Очевидно, это было бы очень сложно реализовать для строк, но я надеюсь, что люди смогут увидеть концепцию желания перерезать объект (List, Dict, DataFrame,...), исключив набор известных разреженных элементов

Мой неандертальский способ выполнить отрицательную индексацию в стиле R в Python:

import numpy as np

my_list = [0,1,2,3,4,5,6,7,8,9]
my_neg_slice = [-2, -8, 0, -5]

# Convert my_list to a numpy array as it much easier to work with
step0 = np.array(my_list)

# Same for the negative_slices
step1 = np.array(my_neg_slice)

# Identify the indexes that are negative (assume 0 implies exclude)
step2 = step1 <= 0

# For the negative indexes, flip the sign so they are positive
step3 = -step1[step2]

# Generate the complete index for my_list
step4 = np.arange(len(my_list))

# Identify the indices required by exlucing my_neg_slice indices
step5 = np.setdiff1d(step4, step3)

# Make a cup of tea! Maybe time to rewire the brain and think like a snake!
step6 = step0[step5]

print(step6)
[1 3 4 6 7 9]

У меня нет особой проблемы, которую я пытаюсь взломать, я просто ищу, чтобы понять свое понимание возможностей с индексацией? Спасибо заранее. Берти.

Ответ 1

Поскольку вы отметили этот pandas, давайте сделаем my_list a Series:

In [11]: my_list = pd.Series(my_list)

и пусть фактически использовать (более питонический) "отрицательный индекс" для использования положительных значений, если мы не хотим этого делать, тогда используйте понимание списка для этой части с тем же эффектом (или если это было само множество или Series, просто возьмите -my_neg_slice):

In [12]: my_neg_slice = [2, 8, 0, 5]

Тогда, поскольку индекс my_list является просто перечислением (в этом случае), мы можем вычесть:

In [13]: my_list.index - my_neg_slice
Out[13]: Int64Index([1, 3, 4, 6, 7, 9], dtype=int64)

и посмотрите на эти элементы в остальных позициях:

In [14]: my_list.iloc[my_list.index - my_neg_slice]
Out[14]: 
1    1
3    3
4    4
6    6
7    7
9    9
dtype: int64

Ответ 2

Удивленный никто не упомянул метод drop в pandas:

In [8]: s
Out[8]: 
0    0
1    1
2    2
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int64

In [9]: s.drop([2, 8, 0, 5])
Out[9]: 
1    1
3    3
4    4
6    6
7    7
9    9
dtype: int64

Ответ 3

Используйте наборы:

>>> set([0,1,2,3,4,5,6,7,8,9]) - set([0,2,5,8])
set([1, 3, 4, 6, 7, 9])

(используйте положительные значения вместо отрицательных).

Ответ 4

Это использует немного другой формат для my_neg_slice, но следующим является метод Pythonic для фильтрации итерации в том, как вы описываете:

>>> my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> my_neg_slice = set([2, 8, 0, 5])
>>> [x for i, x in enumerate(my_list) if i not in my_neg_slice]
[1, 3, 4, 6, 7, 9]

Ответ 5

Это интересный вопрос! Я думал, что попытаюсь предоставить версию numpy. Насколько я знаю, он должен будет полагаться на процесс, подобный тому, который вы дали, когда вы создали список индексов в данных, а затем устранили те, которые вам не нужны.

mask = np.ones(len(my_list), dtype=bool)
for i in my_neg_slice:
    mask[i] = False
my_list[mask]

Немного расточительно, однако, в том смысле, что в вашем массиве масок должно быть столько элементов, сколько my_list. Ответ @F.J хорош, потому что он сохраняет разреженность "не в" фрагменте.

Update

Просто нашел сообщение для рассылки numpy, которое, похоже, подтверждает, что вам нужно будет сделать это, используя какую-то маскировку: http://mail.scipy.org/pipermail/numpy-discussion/2008-May/034021.html