pandas row operation to keep only the right most non zero value per row
<p>How to keep the right most number in each row in a dataframe?</p>

<pre><code>a = [[1, 2, 0], [1, 3, 0], [1, 0, 0]]
df = pd.DataFrame(a, columns=['col1','col2','col3'])
df

      col1  col2    col3
row0    1   2       NaN
row1    1   3       0
row2    1   0       0
</code></pre>

<p>Then after transformation</p>

<pre><code>      col1  col2    col3
row0    0   2       0
row1    0   3       0
row2    1   0       0
</code></pre>

<p>Based on the suggestion by <a href="http://stackoverflow.com/users/3293881/divakar">divakar</a> I've come up with the following:</p>

<pre><code>import pandas as pd
a = [[1, 2, 0, None], 
     [1, 3, 0,0], 
     [1, 0, 0,0], 
     [1, 0, 0,0], 
     [1, 0, 0,0], 
     [0, 0, 0,1]]

df = pd.DataFrame(a, columns=['col1','col2','col3','col4'])
df.fillna(value=0,inplace=True) # Get rid of non numeric items
a

[[1, 2, 0, None],
 [1, 3, 0, 0],
 [1, 0, 0, 0],
 [1, 0, 0, 0],
 [1, 0, 0, 0],
 [0, 0, 0, 1]]

# Return index of first occurrence of maximum over requested axis.
# 0 or 'index' for row-wise, 1 or 'columns' for column-wise
df.idxmax(1)

0    col2
1    col2
2    col1
3    col1
4    col1
5    col4
dtype: object
</code></pre>

<p>Create a matrix to mask values</p>

<pre><code>numberOfRows = df.shape[0]
df_mask= pd.DataFrame(columns=df.columns,index=np.arange(0, numberOfRows))
df_test.fillna(value=0,inplace=True) # Get rid of non numeric items

# Add mask entries
for row,col in enumerate(df.idxmax(1)):
   df_mask.loc[row,col] = 1

df_result=df*df_mask
df_result

col1    col2    col3    col4
0   0   2   0   0.0
1   0   3   0   0.0
2   1   0   0   0.0
3   1   0   0   0.0
4   1   0   0   0.0
5   0   0   0   1.0
</code></pre>

<p>Working at NumPy level, here's one vectorized approach using <a href="http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html" rel="nofollow"><code>broadcasting</code></a> -</p>

<pre><code>np.where(((a!=0).cumsum(1).argmax(1))[:,None] == np.arange(a.shape[1]),a,0)
</code></pre>

<p>Sample run -</p>

<pre><code>In [7]: a # NumPy array
Out[7]: 
array([[1, 2, 0],
       [1, 3, 0],
       [1, 0, 0]])

In [8]: np.where(((a!=0).cumsum(1).argmax(1))[:,None] == np.arange(a.shape[1]),a,0)
Out[8]: 
array([[0, 2, 0],
       [0, 3, 0],
       [1, 0, 0]])
</code></pre>

<hr>

<p>Porting it to <code>pandas</code>, we would have an implementation like so -</p>

<pre><code>idx = (df!=0).values.cumsum(1).argmax(1)
df_out = df*(idx[:,None] == np.arange(df.shape[1]))
</code></pre>

<p>Sample run -</p>

<pre><code>In [19]: df
Out[19]: 
   col1  col2  col3  col4
0     1     2     0   0.0
1     1     3     0   0.0
2     2     2     2   0.0
3     1     0     0   0.0
4     1     0     0   0.0
5     0     0     0   1.0

In [20]: idx = (df!=0).values.cumsum(1).argmax(1)

In [21]: df*(idx[:,None] == np.arange(df.shape[1]))
Out[21]: 
   col1  col2  col3  col4
0     0     2     0   0.0
1     0     3     0   0.0
2     0     0     2   0.0
3     1     0     0   0.0
4     1     0     0   0.0
5     0     0     0   1.0
</code></pre>

python pandas dataframe