3

I'd like to get the row and column labels for values matching some condition in a dataframe. Just to keep it interesting, I need it to work with a hierarchical (multi-)index. For example:

df = pd.DataFrame(np.arange(16).reshape(4, 4), columns=pd.MultiIndex.from_product((('a', 'b'), ('x', 'y'))))

    a       b    
    x   y   x   y
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15

Now let's say I want the row and column labels of the elements where

df % 6 == 0

       a             b       
       x      y      x      y
0   True  False  False  False
1  False  False   True  False
2  False  False  False  False
3   True  False  False  False

I would like to get

[(0, ('a', 'x')), (1, ('b', 'x')), (3, ('a', 'x'))]

Please note I would like a general solution, that does not rely on the index being monotonic, or the particular selection in my example. This questions has been asked many times, but the answers do not generalize:

Is this really so hard in Pandas?

Community
  • 1
  • 1
Doctor J
  • 5,974
  • 5
  • 44
  • 40

1 Answers1

5

Use np.where to obtain the ordinal indices of the True values:

import numpy as np
import pandas as pd
df = pd.DataFrame(np.arange(16).reshape(4, 4), 
                  columns=pd.MultiIndex.from_product((('a', 'b'), ('x', 'y'))))

mask = (df % 6 == 0)
i, j = np.where(mask)
print(list(zip(df.index[i], df.columns[j])))

yields

[(0, ('a', 'x')), (1, ('b', 'x')), (3, ('a', 'x'))]
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677