efficiently replace values from a column to another column Pandas DataFrame
<p>I have a Pandas DataFrame like the following one: </p>

<pre><code>   col1 col2 col3
1   0.2  0.3  0.3
2   0.2  0.3  0.3
3     0  0.4  0.4
4     0    0  0.3
5     0    0    0
6   0.1  0.4  0.4
</code></pre>

<p>I want to replace the <code>col1</code> values with the values in the second column (<code>col2</code>) only if <code>col1</code> values are equal to 0, and after (for the zero values remaining),  do it again but with the third column (<code>col3</code>). The Desired Result is the next one:</p>

<pre><code>   col1 col2 col3
1   0.2  0.3  0.3
2   0.2  0.3  0.3
3   0.4  0.4  0.4
4   0.3    0  0.3
5     0    0    0
6   0.1  0.4  0.4
</code></pre>

<p>I did it using the <code>pd.replace</code> function, but it seems too slow.. I think must be a faster way to accomplish that. </p>

<pre><code>df.col1.replace(0,df.col2,inplace=True)
df.col1.replace(0,df.col3,inplace=True)
</code></pre>

<p>is there a faster way to do that?, using some other function instead of the <code>pd.replace</code> function?, maybe slicing the <code>df.col1</code> ?</p>

<p>PS1. Additional info: the original goal of the problem is to replace the zero values (in <code>col1</code>) with the statistic mode of some groups of ids. That is why I have <code>col2</code>(best mode, first option of replacement) and <code>col3</code>(last mode, still functional but not so desirable as <code>col2</code>). </p>

<p>Using <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html" rel="nofollow"><code>np.where</code></a> is faster.  Using a similar pattern as you used with <code>replace</code>:</p>

<pre><code>df['col1'] = np.where(df['col1'] == 0, df['col2'], df['col1'])
df['col1'] = np.where(df['col1'] == 0, df['col3'], df['col1'])
</code></pre>

<p>However, using a nested <code>np.where</code> is slightly faster:</p>

<pre><code>df['col1'] = np.where(df['col1'] == 0, 
                      np.where(df['col2'] == 0, df['col3'], df['col2']),
                      df['col1'])
</code></pre>

<p><strong>Timings</strong></p>

<p>Using the following setup to produce a larger sample DataFrame and timing functions:</p>

<pre><code>df = pd.concat([df]*10**4, ignore_index=True)

def root_nested(df):
    df['col1'] = np.where(df['col1'] == 0, np.where(df['col2'] == 0, df['col3'], df['col2']), df['col1'])
    return df

def root_split(df):
    df['col1'] = np.where(df['col1'] == 0, df['col2'], df['col1'])
    df['col1'] = np.where(df['col1'] == 0, df['col3'], df['col1'])
    return df

def pir2(df):
    df['col1'] = df.where(df.ne(0), np.nan).bfill(axis=1).col1.fillna(0)
    return df

def pir2_2(df):
    slc = (df.values != 0).argmax(axis=1)
    return df.values[np.arange(slc.shape[0]), slc]

def andrew(df):
    df.col1[df.col1 == 0] = df.col2
    df.col1[df.col1 == 0] = df.col3
    return df

def pablo(df):
    df['col1'] = df['col1'].replace(0,df['col2'])
    df['col1'] = df['col1'].replace(0,df['col3'])
    return df
</code></pre>

<p>I get the following timings:</p>

<pre><code>%timeit root_nested(df.copy())
100 loops, best of 3: 2.25 ms per loop

%timeit root_split(df.copy())
100 loops, best of 3: 2.62 ms per loop

%timeit pir2(df.copy())
100 loops, best of 3: 6.25 ms per loop

%timeit pir2_2(df.copy())
1 loop, best of 3: 2.4 ms per loop

%timeit andrew(df.copy())
100 loops, best of 3: 8.55 ms per loop
</code></pre>

<p>I tried timing your method, but it's been running for multiple minutes without completing.  As a comparison, timing your method on just the 6 row example DataFrame (not the much larger one tested above) took 12.8 ms.</p>

python pandas replace dataframe