我正试图摆脱在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?
答案 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))
是转换为0
和1
的布尔掩码,因此删除了第一行和第二行。
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()
来获得相同的结果。)