Python中的R样式否定索引。不要切片

时间:2013-08-14 21:54:43

标签: python r pandas

我的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实现的批评,因为我非常喜欢它)。有人在Python中实现了R_Style_Negative_Indexing吗?我是Python的新手,所以这种类型的索引可能已经存在?也许有人创建了一个自定义扩展(抱歉,如果这不是正确的术语)来扩展适当的库?

显然,对于字符串实现这将是非常棘手的,但我希望人们可以通过排除一组已知的稀疏元素来看到想要切入对象(List,Dict,DataFrame,...)的概念?

我的尼安德特人在Python中执行负R风格索引的方法:

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]

我没有特别的问题,我正试图破解,我只是想通过索引建立我对可能性的理解?提前谢谢了。 贝尔蒂。

5 个答案:

答案 0 :(得分:5)

既然你已经标记了这只大熊猫,那就让my_list成为一个系列:

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

让我们实际上使用(更多pythonic)“负指数”来使用正数,如果我们不想这样做那么使用列表理解来获得相同的效果(或者如果它本身就是一个numpy数组)或系列然后只需-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

答案 1 :(得分:3)

惊讶没有人提到熊猫中的drop方法:

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

答案 2 :(得分:2)

使用套装:

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

(使用正值而不是负值)。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

这是一个有趣的问题!我以为我会尝试提供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的答案很好,因为它保留了“不在”切片的稀疏性。

更新

刚刚找到一个numpy邮件列表帖子似乎确认您需要使用某种屏蔽方式执行此操作:http://mail.scipy.org/pipermail/numpy-discussion/2008-May/034021.html