使用.drop()的Pandas布尔索引错误

时间:2017-07-10 03:55:16

标签: python python-3.x pandas

我正试图摆脱在Pandas中使用链式赋值。虽然我发现这种行为试图更新我的作业实践,但我认为这与作业本身无关。如下面的示例所示,它似乎是过滤过程本身。这似乎是一个错误...但也许我错过了什么?

df = pd.DataFrame( data = {
                         'acol'  : [1.0, 3.00, 11.0, 31.0, 100.0, 314.0],
                         'bcol' :  [1.0, 3.14, 10.1, 31.4,  81.2, 314.1]
                        })

我的旧方法是过滤和重新分配,有条件地保留一些行:

In[20]: df[(df.acol > df.bcol) & (df.acol > 10)]

Out[20]:
    acol    bcol
2   11.0    10.1
4   100.0   81.2

新的,更负责任的我正在尝试使用.drop()功能......但结果似乎不一致:

In[21]: df.drop((df.acol <= df.bcol) | (df.acol <= 10), axis=0)
Out[21]: 
    acol    bcol
2   11.0    10.1
3   31.0    31.4
4   100.0   81.2
5   314.0   314.1

De Morgan的定理说那些应该给出相同的结果(https://en.wikipedia.org/wiki/De_Morgan%27s_laws)。

我已经检查了文档(http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing),但似乎没有提到这种行为。我知道数据帧索引存在一些歧义,但通过使用按位运算符,我应该避免这种情况(Pandas boolean DataFrame selection ambiguity)。

更令人担心的是,如果我从输入数据的每个列表中删除第0个条目,使用.drop()时会得到不同的结果(第2行消失)!

我正在使用Python 3.6,Pandas 0.20.2

HALP?

2 个答案:

答案 0 :(得分:3)

您需要boolean indexing df.index,然后drop

print (df.index[((df.acol <= df.bcol) | (df.acol <= 10))])
Int64Index([0, 1, 3, 5], dtype='int64')

df1 = df.drop(df.index[((df.acol <= df.bcol) | (df.acol <= 10))])
print (df1)
    acol  bcol
2   11.0  10.1
4  100.0  81.2

在您的代码中:

df.drop((df.acol <= df.bcol) | (df.acol <= 10))

是转换为01的布尔掩码,因此删除了第一行和第二行。

print ((df.acol <= df.bcol) | (df.acol <= 10))
0     True
1     True
2    False
3     True
4    False
5     True
dtype: bool

所以在我看来,使用drop这里有点过于复杂的解决方案,更好的是仅使用boolean indexing

df[(df.acol > df.bcol) & (df.acol > 10)]

query的替代解决方案:

df1 = df.query("acol > bcol & acol > 10")
print (df1)
    acol  bcol
2   11.0  10.1
4  100.0  81.2

答案 1 :(得分:1)

df.drop()适用于标签或索引。如果要将其与布尔掩码一起使用,请执行

df.drop(df.index[(df.acol <= df.bcol) | (df.acol <= 10)])

包含inplace=True参数而不是重新分配也更有效。

(至于为什么会发生这种情况,据我所知,这只是出乎意料的行为:通过将[ True, True, False, True, False, True]作为参数传递给.drop()来获得相同的结果。)