用列列表和多个条件建立索引

时间:2019-01-11 16:50:41

标签: python python-3.x pandas

尝试获取某些列的零列,而另一些列的零列。

import pandas as pd
import numpy as np
df=pd.DataFrame({'t':[0,0,0,np.nan],'t2':[0,0,2,3],'t3':[1,0,0,np.nan],'t4':[0,np.nan,2,3]})
zero=['t','t3']
nozero=['t2','t4']

数据框:

     t  t2   t3   t4
0  0.0   0  1.0  0.0
1  0.0   0  0.0  NaN
2  0.0   2  0.0  2.0
3  NaN   3  NaN  3.0

我尝试过:

df[((df[zero]==0).any(axis=1))&((df[nozero]!=0).any(axis=1))]

给出

     t  t2   t3   t4
1  0.0   0  0.0  NaN
2  0.0   2  0.0  2.0

也尝试过:

df[((df[zero]==0)&(df[nozero]!=0)).any(axis=1)]

给出一个空的数据框。

预期:

     t  t2   t3   t4
2  0.0   2  0.0  2.0

任何帮助都会很棒。谢谢。

编辑说明:

对于每对(t,t2和t3,t4),我都需要两个条件(ALL)都为真(零== 0和nozero!= 0),但是如果该行中的任何一对都为真,我希望行。

例如,来自以下数据框:

df = pd.DataFrame({'t': [0, 0, 11,0], 't2': [0, 0, 0, 0], 'z3': [0, 0, 12, 0], 't4': [0, 0, 2, 0],
                   't5': [0, 0, 0, 0], 'z6': [0, 0, 4, 0], 't7': [1, 1, 0, 1], 't8': [1, 1, 0, 1],
                   'z9': [1, 1, 0, 1], 't10': [1, 1, 0, 1], 't11': [1, 1, 0, 1], 'z12': [1, 1, 0, 1]})

nozero=['z3','z6','z9','z12']
zero=list(set(df.columns)-set(nozero))

    t  t2  z3  t4  t5  z6  t7  t8  z9  t10  t11  z12
0   0   0   0   0   0   0   1   1   1    1    1    1
1   0   0   0   0   0   0   1   1   1    1    1    1
2  11   0  12   2   0   4   0   0   0    0    0    0
3   0   0   0   0   0   0   1   1   1    1    1    1

我只想要第2行,因为any(t,t2)为零而z3不为零。

编辑说明:

以下代码生成我要保留的行(索引= 2)。有没有比.any或.all更为有效的方法? (因为这需要追加行,分配内存,循环等)

import pandas as pd

    df = pd.DataFrame({'t': [0, 0, 11,0], 't2': [0, 0, 0, 0], 'z3': [0, 0, 12, 0], 't4': [0, 0, 2, 0],
                       't5': [0, 0, 0, 0], 'z6': [0, 0, 4, 0], 't7': [1, 1, 0, 1], 't8': [1, 1, 0, 1],
                       'z9': [1, 1, 0, 1], 't10': [1, 1, 0, 1], 't11': [1, 1, 0, 1], 'z12': [1, 1, 0, 1]})
    nozero=['z3','z6','z9','z12']
    zero1=['t','t4','t7','t10']
    zero2=['t2','t5','t8','t11']
    for x,y,z in zip(zero1, zero2, nozero):
        print(df[((df[x]==0) | (df[y]==0)) & (df[z]!=0)])

3 个答案:

答案 0 :(得分:0)

我认为是因为NaN。 NaN != 0 is True

df[((df[zero]==0).any(axis=1))&((df[nozero]!=0).any(axis=1))].dropna()

df[((df[zero]==0).any(axis=1))&((df[nozero]!=0).any(axis=1))&(df[zero+nozero].notnull().all(axis=1))]

      t  t2   t3  t4
2   0.0   2  0.0   2




df

     t  t10 t11 t2  t4  t5  t7  t8  z12 z3  z6  z9
0    0    1   1  0   0   0   1   1    1  0   0   1 
1    0    0   0  0   0   0   0   0    1 12   4   1
2   11    1   0  0   2   0   1   0    0  0   0   0
3    0    1   1  0   0   0   1   1    1  0   0   1

df[((df[zero]==0).all(1))&((df[nozero]!=0).all(1))&(df[zero+nozero].notnull().all(1))]

    t t10 t11  t2  t4  t5  t7  t8 z12   z3  z6  z9
1   0   0   0   0   0   0   0   0   1   12   4   1

答案 1 :(得分:0)

根据与@coldspeed的讨论,看来您正在使用看起来更像的数据框

     t   t2   t3   t4
0  0.0  0.0  1.0  0.0
1  0.0  0.0  0.0  NaN
2  0.0  2.0  0.0  2.0
3  NaN  3.0  NaN  3.0
4  0.0  1.0  0.0  0.0

在转换了建议的@coldspeed之类的数据类型之后,您可以继续并使用它来选择所需的数据。

In [193]: df[((df[zero] == 0).all(1) & (df[nozero] != 0).any(1))]
Out[193]: 
     t   t2   t3   t4
1  0.0  0.0  0.0  NaN
2  0.0  2.0  0.0  2.0
4  0.0  1.0  0.0  0.0

第一个条件(df[zero]==0).all(1)zero列中找到所有0的值(all(1)告诉熊猫按列减少)。第二个条件是在nozero列中找到任何不为零的值,正如@Ananay所说,其中包括NaN

就像@Ananay在回答中说的那样,您可以使用NaN删除具有dropna()值的行,这样最终结果就是

In [194]: df[((df[zero] == 0).all(1) & (df[nozero] != 0).any(1))].dropna()
Out[194]: 
     t   t2   t3   t4
2  0.0  2.0  0.0  2.0
4  0.0  1.0  0.0  0.0

我还建议您阅读有关.any().all()方法的更多信息。

编辑

我可以做到

df[((df['t']==0) | (df['t2']==0)) & (df['z3']!=0)]

但我不知道您是否要具体说明。问题只是为我以前的方法找到正确的布尔条件。我们希望第3行返回True,其他行返回False。您可以尝试将此问题重命名为“布尔索引以根据列列表的条件查找值”或进行搜索。

答案 2 :(得分:0)

由于我无法使用.any或.all获得所需的行,因此我编写了一种变通方法代码。如果您发现任何更有效的方法而无需遍历各列,请告诉我。感谢所有帮助@Ananay Mital,@ m42op64,@ coldspeed。

import pandas as pd

df = pd.DataFrame({'t': [0, 0, 11,0], 't2': [0, 0, 0, 0], 'z3': [0, 0, 12, 0], 't4': [0, 0, 2, 0],
                   't5': [0, 0, 0, 0], 'z6': [0, 0, 4, 0], 't7': [1, 1, 0, 1], 't8': [1, 1, 0, 1],
                   'z9': [1, 1, 0, 1], 't10': [1, 1, 0, 1], 't11': [1, 1, 0, 1], 'z12': [1, 1, 0, 1]})
nozero=['z3','z6','z9','z12']
zero1=['t','t4','t7','t10']
zero2=['t2','t5','t8','t11']
indices=set()
for x,y,z in zip(zero1, zero2, nozero):
    i=df[((df[x]==0) | (df[y]==0)) & (df[z]!=0)].index.values
    indices.update(i)
print(df.loc[list(indices)])

输出

    t  t2  z3  t4  t5  z6  t7  t8  z9  t10  t11  z12
2  11   0  12   2   0   4   0   0   0    0    0    0