Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R style Negative Indexing in Python. Take NOT IN Slices

Tags:

python

pandas

r

My R programming head is wired to use negative slicing indexes to exclude elements.

As an example:

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

Would return

[1 3 4 6 7 9]

i.e. return all indexes not in (0, 2, 5, 8).

This is more of a question to satisfy my curiosity as the Pythonic negative indexing is quite novel to me (this is not a critique of Python's implementation as I quite like it). Has anyone implemented a R_Style_Negative_Indexing in Python? I am very new to Python so this type of indexing may already exist? Maybe someone has created a custom extension (sorry if this is not the correct terminology) to extend an appropriate library?

Obviously, this would be very tricky to implement for strings, but I am hoping people can see the concept of wanting to slice into an object (List, Dict, DataFrame, ...) by excluding a set of known sparse elements?

My Neanderthal way to perform the negative R style indexing in 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's 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]

I dont have a particular problem that I am trying to crack, I am simply looking to build my understanding of the possibilities with indexing? Many thanks in advance. Bertie.

like image 721
Bertie Avatar asked Aug 14 '13 21:08

Bertie


1 Answers

Since you've tagged this pandas, let's make my_list a Series:

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

and let's actually take the (more pythonic) "negative index" to use positives, if we don't want to do that then use a list comprehension for this part to the same effect (or if it was itself a numpy array or Series then just take -my_neg_slice):

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

Then, since the index of my_list is simply an enumeration (in this case), we can subtract:

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

and look at those elements in the remaining positions:

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
like image 132
Andy Hayden Avatar answered Nov 15 '22 13:11

Andy Hayden