Q:

Looping though Dataframes Doesnt feel right

Hey there guys  I have come to Python via Excel VBA as a way of dealing with large data sets that I'm using. 
I have several datasets that is depth based and I need to "populate up" some data sets to match the finest data resolution actual (for when I get to image clustering ) .   The images are getting me data on 0.01mm  while some of my measured  dataset are on samples that are about 40mm in  size.  To scale the measured data from a point im using the code below.  
I get the feeling I'm missing the point with Dataframes and falling back on my VBA (bad??)  habits
The dataset I'm testing this on is about 50,000 rows and the size variable is set at 200 (ie 200 x .1mm each way for 40mm total). 
At some stage in the future ill be doing this with IR image array style data for each of a b c sets below.  
I can see that because of the iteration this is currently taking a lit of time.   Hoping there is a brain out there that can see though my fumbling code
def new_depth(df, size):
    x=0
    for i in df['Depth']:
        x=+1
        measured_data = df.iloc[x, :]
        for y in range(size):
            if y!=0:
                added_p = i+y
                added_n = i-y
                measured_data["Depth"] = added_p
                df.loc[len(df)] = measured_data
                measured_data["Depth"] = added_n
                df.loc[len(df)]=measured_data

Ignoring the scale of things the general concept is:
Initial df
Depth  | Item1 | Item 2 | Item3 
-----  |-------|--------|------
10.01  |   a   |   b    |   c
10.02  |   d   |   e    |   f
10.03  |   h   |   i    |   j

New df
Depth    | Item1 | Item 2 | Item3 
-----    |-------|--------|------
etc
10.008   |   a   |   b    |   c
10.009   |   a   |   b    |   c
**10.010   |   a   |   b    |   c**
10.011   |   a   |   b    |   c
10.012   |   a   |   b    |   c
etc
---------------------------------
etc
10.018   |   d   |   e    |   f
10.019   |   d   |   e    |   f
**10.020   |   d   |   e    |   f**
10.021   |   d   |   e    |   f
10.022   |   d   |   e    |   f
etc

A:

step=0.001
df2 = df.reindex(pd. Float64Index(np.arange(df.index[0], df.index[-1]+step, step=step).round(3))).ffill()

This uses 'Depth' as index
Range
np.arange(df.index[0], df.index[-1]+step, step=step).round(3) makes a range
array([ 10.01 ,  10.011,  10.012,  10.013,  10.014,  10.015,  10.016,
        10.017,  10.018,  10.019,  10.02 ,  10.021,  10.022,  10.023,
        10.024,  10.025,  10.026,  10.027,  10.028,  10.029,  10.03 ])

The df.index[-1]+step is to make sure the last index is included.  The .round(3) is to prevent rounding errors.  Floating point comparison is a tricky thing. 
Index
The pd. Float64Index(<range>) makes the index.  It also works without this step, but makes it more explicit. 
Reindex
The df.reindex(<index>) sets this created index as the new index for the DataFrame, and tries to find older entries in df that match this index.  It fills the other rows with NaN
    Item1   Item 2  Item3
Depth           
10.010  a   b   c
10.011  NaN     NaN     NaN
10.012  NaN     NaN     NaN
10.013  NaN     NaN     NaN
10.014  NaN     NaN     NaN
10.015  NaN     NaN     NaN
10.016  NaN     NaN     NaN
10.017  NaN     NaN     NaN
10.018  NaN     NaN     NaN
10.019  NaN     NaN     NaN
10.020  d   e   f
10.021  NaN     NaN     NaN
10.022  NaN     NaN     NaN
10.023  NaN     NaN     NaN
10.024  NaN     NaN     NaN
10.025  NaN     NaN     NaN
10.026  NaN     NaN     NaN
10.027  NaN     NaN     NaN
10.028  NaN     NaN     NaN
10.029  NaN     NaN     NaN
10.030  h   i   j

ffil
the .ffil() fills empty items with the item from the preceding row.  If you only need to fill maximum 5 items you can use .ffil(limit=5).  ffill is a synonym for .fillna(method='ffill)

