retrieve series of slices of column headers based on truth of dataframe values
<p>consider the dataframe <code>df</code></p>

<pre><code>np.random.seed([3,1415])
df = pd.DataFrame(np.random.choice((0, 1), (3, 3)),
                  columns=['blah', 'meep', 'zimp'])
df
</code></pre>

<p><a href="http://i.stack.imgur.com/H2ovB.png" rel="nofollow"><img src="http://i.stack.imgur.com/H2ovB.png" alt="enter image description here"></a></p>

<hr>

<p><strong><em>question</em></strong><br>
what is the most efficient way to slice <code>df.columns</code> with each row of <code>df</code>?<br>
(for this example and at scale)</p>

<p><strong><em>expected results</em></strong></p>

<pre><code>0          [meep]
1          [blah]
2    [blah, zimp]
dtype: object
</code></pre>

<hr>

<h1>At Scale</h1>

<p>I confirmed that @jezrael, @boud, and my answer all produce the same results.  Below is the dataframe I used to test the scale of each solution</p>

<pre><code>from string import letters
import pandas as pd
import numpy as np

mux = pd.MultiIndex.from_product([list(letters), list(letters)])

df = pd.DataFrame(np.arange(52 ** 4).reshape(52 ** 2, -1) % 3 % 2, mux, mux)
</code></pre>

<p><strong><em>setup for boud</em></strong>  </p>

<pre><code>s = pd.Series([[x] for x in df], df.columns)
</code></pre>

<p><strong><em>setup for pirsquared</em></strong></p>

<pre><code>num = df.columns.nlevels
lvls = list(range(num))
rlvls = [x * -1 - 1 for x in lvls]
xsl = lambda x: x.xs(x.name).index.tolist()
</code></pre>

<p><strong><em>results</em></strong>  </p>

<p><a href="http://i.stack.imgur.com/HIHqb.png" rel="nofollow"><img src="http://i.stack.imgur.com/HIHqb.png" alt="enter image description here"></a></p>

<p><strong><em>small df</em></strong>  </p>

<p><a href="http://i.stack.imgur.com/s0ZYx.png" rel="nofollow"><img src="http://i.stack.imgur.com/s0ZYx.png" alt="enter image description here"></a></p>

<p>use <code>where</code> and <code>stack</code> to drop <code>0</code>s then grab indices left over</p>

<pre><code># number of levels in columns
num = df.columns.nlevels
# handy list for stacking
lvls = list(range(num))
# reverse (sort of) list for unstacking
rlvls = [x * -1 - 1 for x in lvls]

# get just levels in index that used to be columns
xsl = lambda x: x.xs(x.name).index.tolist()

# where is faster than replace
# when I stack, I'll drop all np.nan
# then just grab the indices that are left
df.where(df, np.nan).stack(lvls).groupby(level=lvls).apply(xsl)

0          [meep]
1          [blah]
2    [blah, zimp]
dtype: object
</code></pre>

python pandas numpy