使用Pandas从另一个数据框中删除一个数据框

时间:2017-06-14 13:22:05

标签: python pandas dataframe compare difference

我有两个不同大小的数据框(df1 nad df2)。我想从df1中删除存储在df2内的所有行。{/ p>

所以,如果我df2等于:

     A  B
0  wer  6
1  tyu  7

df1等于:

     A  B  C
0  qwe  5  a
1  wer  6  s
2  wer  6  d
3  rty  9  f
4  tyu  7  g
5  tyu  7  h
6  tyu  7  j
7  iop  1  k

最终结果应如下:

     A  B  C
0  qwe  5  a
1  rty  9  f
2  iop  1  k

我能够通过使用for循环实现我的目标,但我想知道是否有更好,更优雅和有效的方法来执行此类操作。

以下是我在需要时编写的代码: 将pandas导入为pd

df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'],
                    'B' : [    5,     6,     6,     9,     7,     7,     7,     1],
                    'C' : ['a'  ,   's',   'd',   'f',   'g',   'h',   'j',   'k']})

df2 = pd.DataFrame({'A' : ['wer', 'tyu'],
                    'B' : [    6,     7]})

for i, row in df2.iterrows():
    df1 = df1[(df1['A']!=row['A']) & (df1['B']!=row['B'])].reset_index(drop=True)

5 个答案:

答案 0 :(得分:7)

merge与外联接一起使用query进行过滤,最后按drop删除辅助列:

df = pd.merge(df1, df2, on=['A','B'], how='outer', indicator=True)
       .query("_merge != 'both'")
       .drop('_merge', axis=1)
       .reset_index(drop=True)
print (df)
     A  B  C
0  qwe  5  a
1  rty  9  f
2  iop  1  k

答案 1 :(得分:3)

您可以使用np.in1d检查df2中是否存在df1中的任何行。然后将其用作反转掩码,从df1中选择行。

df1[~df1[['A','B']].apply(lambda x: np.in1d(x,df2).all(),axis=1)]\
                   .reset_index(drop=True)
Out[115]: 
     A  B  C
0  qwe  5  a
1  rty  9  f
2  iop  1  k

答案 2 :(得分:2)

pandas有一个名为isin的方法,但这取决于唯一索引。我们可以定义一个lambda函数来创建我们可以在'A''B' df1df2的现有df2import pandas as pd df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'], 'B' : [ 5, 6, 6, 9, 7, 7, 7, 1], 'C' : ['a' , 's', 'd', 'f', 'g', 'h', 'j', 'k']}) df2 = pd.DataFrame({'A' : ['wer', 'tyu'], 'B' : [ 6, 7]}) unique_ind = lambda df: df['A'].astype(str) + '_' + df['B'].astype(str) print df1[~unique_ind(df1).isin(unique_ind(df2))].reset_index(drop=True) 中使用的列。然后我们否定这一点(因为我们希望值不在 A B C 0 qwe 5 a 1 rty 9 f 2 iop 1 k 中)并重置索引:

 <Root>
   <Parties>
      <Party PartyId="Party_1">
         <PartyTypeCode PartyTypeCode="Bastard"></PartyTypeCode>
         <PersonInfo>
            <FirstName>Jon</FirstName>
            <LastName>Snow</LastName>
            <Gender>M</Gender>
         </PersonInfo>
         <EmailAddress>knowsnothing@gmail.com</EmailAddress>
      </Party>
      <Party PartyId="Party_2">
         <PartyTypeCode PartyTypeCode="Stark"></PartyTypeCode>
         <PersonInfo>
            <FirstName>Eddard</FirstName>
            <LastName>Stark</LastName>
         </PersonInfo>
      </Party>
   </Parties>
     <MoreInfo>
         <Parties>
            <PartyRef PartyId="Party_1">
               <PartyRole PartyRoleCode="Nights Watch"></PartyRole>
            </PartyRef>
            <PartyRef PartyId="Party_1">
               <PartyRole PartyRoleCode="Wildling"></PartyRole>
            </PartyRef>
            <PartyRef PartyId="Party_2">
               <PartyRole PartyRoleCode="Kings Hand"></PartyRole>
            </PartyRef>
         </Parties>
   </MoreInfo>
</Root>

打印:

PartyRolecode   FirstName   LastName   Gender   Email Address
-------------   ---------   --------   ------   -------------
Nights Watch    Jon         Snow       M        knowsnothing@gmail.com
Wildling        Jon         Snow       M        knowsnothing@gmail.com
Kings Hand      Eddard      Stark      

答案 3 :(得分:2)

我发现最干净的方法是使用你想要删除的数据帧的索引来使用pandas中的drop:

df1.drop(df2.index, axis=0,inplace=True)

答案 4 :(得分:0)

我认为最干净的方法可以是:

我们有基本数据帧D,并希望删除子集D1。令输出为D2

D2 = pd.DataFrame(D, index = set(D.index).difference(set(D1.index))).reset_index()