Pandas的等价于R中which()函数的方法

19

类似的问题以前被问过,我仍然很难理解如何根据我想设置的条件实际切片python series/pandas dataframe。

在R中,我尝试做的是:

df[which(df[,colnumber] > somenumberIchoose),]

which()函数在数据框中查找列条目的索引,这些条目大于我选择的一个数,并将其作为向量返回。然后,我使用这些行索引来指示我想要在新形式中查看哪些数据框行,并对数据框进行切片。

在Python中有没有相应的方法?我看到了一些关于枚举的参考资料,但在阅读文档之后还不是很理解。目前为止,为了得到行索引,我的代码如下:

indexfuture = [ x.index(), x in enumerate(df['colname']) if x > yesterday]  

然而,我一直收到一个无效的语法错误。我可以通过循环遍历值,并手动执行搜索来绕过此问题,但那似乎非常不符合Python风格且效率低下。

enumerate()函数究竟是做什么的?在Python中找到向量中满足所需参数的值的索引的方式是什么?

注意:我正在使用Pandas进行数据框架操作。


你能展示一下完整的错误回溯吗? - TheSoundDefense
你能尝试这个吗:[a.index() for (a, b) in enumerate(df['colname']) if b > yesterday] - user1971598
只是为了明确,pandas的数据框可以有各种类型的索引,不仅仅是整数。您只想要整数索引,还是实际的原始行索引? - smci
这个问题询问的是which(),它返回一个向量,其中满足某些条件的索引。最佳答案是关于布尔子集的。这篇帖子包含我认为实际等价于which()的内容。 - Hendy
6个回答

14

我可能没有完全理解问题,但是看起来回答比你想象的要简单:

使用 Pandas 的 DataFrame:

df['colname'] > somenumberIchoose

返回一个带有True / False值和DataFrame原索引的pandas系列。

然后,您可以在原始DataFrame上使用该布尔序列并获取您要查找的子集:

df[df['colname'] > somenumberIchoose]

应该足够了。

参见 http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing


2
df[df['colname'] > somenumberIchoose].index 与 R 中的 which() 函数相同。 - Chris

8

根据我对R的了解,你可能更喜欢使用numpy——一种类似于MATLAB的科学计算包。

如果你想要一个数组中所有值可被2整除的索引,则可以使用以下方法。

arr = numpy.arange(10)
truth_table = arr % 2 == 0
indices = numpy.where(truth_table)
values = arr[indices]

使用多维数组也很容易操作。

arr2d = arr.reshape(2,5)
col_indices = numpy.where(arr2d[col_index] % 2 == 0)
col_values = arr2d[col_index, col_indices]

2
+1 如果解决方案更接近 R 语言习惯用法。另外,我不喜欢把所有东西都转换成 pandas 数据框。 - horaceT

3

enumerate()会返回一个迭代器,在每次迭代中都会生成一个包含索引和元素的元组(index, item),因此您不需要再次调用.index()方法。

此外,您的列表推导式语法是错误的:

indexfuture = [(index, x) for (index, x) in enumerate(df['colname']) if x > yesterday]

测试案例:

>>> [(index, x) for (index, x) in enumerate("abcdef") if x > "c"]
[(3, 'd'), (4, 'e'), (5, 'f')]

当然,您不需要拆开元组:
>>> [tup for tup in enumerate("abcdef") if tup[1] > "c"]
[(3, 'd'), (4, 'e'), (5, 'f')]

除非你只对索引感兴趣,那么你可以做一些类似于

>>> [index for (index, x) in enumerate("abcdef") if x > "c"]
[3, 4, 5]

那么 Python: enumerate :: Ruby: each_with_index - Robert Krzyzanowski
没有必要使用enumerate(),它效率低下,即使有需要,pd.DataFrame也有iterrows()来实现同样的功能。 - smci

0
如果你需要额外的陈述,panda.Series允许你在Series之间进行操作(+、-、/、<、*)。
只需将索引相乘即可。
idx1 = df['lat'] == 49
idx2 = df['lng'] > 15 
idx = idx1 * idx2

new_df = df[idx] 

0
一个不错的简单整洁的方法是这样的:
SlicedData1 = df[df.colname>somenumber]]

这可以轻松地扩展到包括其他标准,例如非数字数据:

SlicedData2 = df[(df.colname1>somenumber & df.colname2=='24/08/2018')]

等等...


0

我通常使用.iteritems而不是enumerate。这样可以避免使用.index()

[k for k, v in (df['c'] > t).iteritems() if v]

否则,就必须这样做

df[df['c'] > t].index()

这会重复输入数据框名称,而且可能会非常冗长和繁琐。


我认为只是df.index一个属性,而不是函数。当我使用index()时,出现错误'Int64Index' object is not callable。尽管如此,这两个都实际上回答了如何做到which()的事情,所以我很喜欢! - Hendy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接