Pandas中的R的which()等效方法
这个问题之前有人问过,但我还是不太明白怎么根据我设定的条件来切片一个Python的序列或Pandas的数据框。
在R语言中,我想做的是:
df[which(df[,colnumber] > somenumberIchoose),]
which()函数可以找到数据框中某一列里大于我选择的某个数字的行的索引,并把这些索引返回成一个向量。然后,我就可以用这些行的索引来切片数据框,选择我想在新形式中查看的行。
在Python中有没有类似的方法?我看到有人提到enumerate,但我看了文档后还是不太明白。为了获取行索引,我现在的样本代码看起来是这样的:
indexfuture = [ x.index(), x in enumerate(df['colname']) if x > yesterday]
但是,我总是遇到无效的语法错误。我可以通过循环遍历值,手动搜索来解决这个问题,但这样做感觉非常不符合Python的风格,也不高效。
那么,enumerate()到底是干什么的?在Python中,找到满足特定条件的向量值的索引的正确方法是什么?
注意:我在使用Pandas来处理数据框。
6 个回答
我通常不使用 enumerate
,而是直接用 .iteritems
。这样可以省去一个 .index()
的步骤。也就是说,
[k for k, v in (df['c'] > t).iteritems() if v]
否则,就得这样做:
df[df['c'] > t].index()
这样做会重复输入数据框的名字,而这个名字可能很长,打起来很麻烦。
如果你需要额外的操作,panda.Series 让你可以在 Series 之间进行运算,比如加、减、乘、除。
只需要把索引相乘就可以了:
idx1 = df['lat'] == 49
idx2 = df['lng'] > 15
idx = idx1 * idx2
new_df = df[idx]
enumerate()
是一个函数,它会返回一个迭代器,每次迭代时会给你一个包含 (索引, 项目)
的元组,所以你不需要再调用 .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]
根据我对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]
我可能没有完全理解这个问题,但看起来答案比你想的要简单:
使用 pandas 的 DataFrame:
df['colname'] > somenumberIchoose
这会返回一个 pandas 系列,里面是 True 和 False 的值,并且保留了原 DataFrame 的索引。
然后你可以用这个布尔系列去筛选原 DataFrame,得到你想要的子集:
df[df['colname'] > somenumberIchoose]
这样就够了。
可以查看 http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing