【问题标题】:Querying MultiIndex DataFrame in Pandas在 Pandas 中查询 MultiIndex DataFrame
【发布时间】:2018-10-18 06:05:44
【问题描述】:

我有一个如下所示的 DataFrame:

FirstDF=
              C
A    B      
'a' 'blue'   43
    'green'  59
'b' 'red     56
'c' 'green'  80
    'orange' 72

其中 A 和 B 被设置为索引。我还有一个看起来像这样的 DataFrame:

SecondDF=

    A     B
0  'a'  'green'
1  'b'  'red'
2  'c'  'green'

有没有办法直接查询第一个DataFrame和最后一个DataFrame,得到如下输出?

C
59
56
80

我通过迭代第二个 DataFrame 来做到这一点,如下所示,但我想使用 pandas 逻辑而不是 for 循环来做到这一点。

data=[]
for i in range(SecondDF.shape[0]):
    data.append(FirstDF.loc[tuple(SecondDF.iloc[i])])
data=pd.Series(data)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    merge与参数left_indexright_on一起使用:

    df = FirstDF.merge(SecondDF, left_index=True, right_on=['A','B'])['C'].to_frame()
    print (df)
        C
    0  59
    1  56
    2  80
    

    使用isinMultiIndexes 并通过boolean indexing 过滤的另一种解决方案:

    mask = FirstDF.index.isin(SecondDF.set_index(['A','B']).index)
    #alternative solution
    #mask = FirstDF.index.isin(list(map(tuple,SecondDF[['A','B']].values.tolist())))
    df = FirstDF.loc[mask, ['C']].reset_index(drop=True)
    print (df)
        C
    0  59
    1  56
    2  80
    

    详情

    print (FirstDF.loc[mask, ['C']])
                  C
    A   B          
    'a' 'green'  59
    'b' 'red'    56
    'c' 'green'  80
    

    编辑:

    您可以将merge 与外连接和indicator=True 参数一起使用,然后按boolean indexing 过滤:

    df1=FirstDF.merge(SecondDF, left_index=True, right_on=['A','B'], indicator=True, how='outer')
    print (df1)
        C    A         B     _merge
    2  43  'a'    'blue'  left_only
    0  59  'a'   'green'       both
    1  56  'b'     'red'       both
    2  80  'c'   'green'       both
    2  72  'c'  'orange'  left_only
    
    mask = df1['_merge'] != 'both'
    df1 = df1.loc[mask, ['C']].reset_index(drop=True)
    print (df1)
        C
    0  43
    1  72
    

    对于第二种解决方案,通过 ~ 反转布尔掩码:

    mask = FirstDF.index.isin(SecondDF.set_index(['A','B']).index)
    #alternative solution
    #mask = FirstDF.index.isin(list(map(tuple,SecondDF[['A','B']].values.tolist())))
    df = FirstDF.loc[~mask, ['C']].reset_index(drop=True)
    print (df)
        C
    0  43
    1  72
    

    【讨论】:

    • 有没有相反的方法?就像,使用相同的数据帧,得到:C 43 72。
    【解决方案2】:
    FirstDF.loc[zip(SecondDF['A'],SecondDF['B']),]
    

    说明:-

    想法是从第二个数据帧中获取索引并在第一个数据帧上使用它们。 对于多索引,您可以传递索引的元组来获取行。

    FirstDF.loc[('bar','two'),] 
    

    将为您提供第一个索引为“bar”且第二个索引为“two”的所有行。

    FirstDF.loc[(SecondDF['A'],SecondDF['B']),] 
    

    直接从您想要的 SecondDF 获取这些索引,但问题是它将获取“A”和“B”的所有组合。所以添加 zip 将只采用 SecondDF 中同一行的索引

    【讨论】:

      【解决方案3】:

      可以使用merge得到结果;

      In [35]: df1
      Out[35]:
         A       B   C
      0  a    blue  43
      1  a   green  59
      2  b     red  56
      3  c   green  80
      4  c  orange  72
      
      In [36]: df2
      Out[36]:
         A      B
      0  a  green
      1  b    red
      2  c  green
      
      In [37]: pd.merge(df1, df2, on=['A', 'B'])['C']
      Out[37]:
      0    59
      1    56
      2    80
      Name: C, dtype: int64
      

      【讨论】:

        【解决方案4】:

        好的,我找到了答案:

        tuple_list = list(map(tuple,SecondDF.values))
        insDF = FirstDF.loc[tuple_list].dropna()
        outsDF = FirstDF.loc[~FirstDF.index.isin(tuple_list)]
        

        这给出了 FirstDF 中存在的值和不存在的值。 此处使用 dropna 方法是因为该查询将 SecondDF 中不在 FirstDF 中的值保留为 NaN,因此应将其删除。

        【讨论】:

          猜你喜欢
          • 2022-12-04
          • 2023-04-08
          • 2019-05-20
          • 2017-08-25
          • 2016-11-06
          • 1970-01-01
          • 2019-05-24
          相关资源
          最近更新 更多