Compare 2 Pandas dataframes, row by row, cell by cell
<p>I have 2 dataframes, <code>df1</code> and <code>df2</code>, and want to do the following, storing results in <code>df3</code>: </p>

<pre><code>for each row in df1:

    for each row in df2:

        create a new row in df3 (called "df1-1, df2-1" or whatever) to store results 

        for each cell(column) in df1: 

            for the cell in df2 whose column name is the same as for the cell in df1:

                compare the cells (using some comparing function func(a,b) ) and, 
                depending on the result of the comparison, write result into the 
                appropriate column of the "df1-1, df2-1" row of df3)
</code></pre>

<p>For example, something like:</p>

<pre><code>df1
A   B    C      D
foo bar  foobar 7
gee whiz herp   10

df2
A   B   C      D
zoo car foobar 8

df3
df1-df2 A             B              C                   D
foo-zoo func(foo,zoo) func(bar,car)  func(foobar,foobar) func(7,8)
gee-zoo func(gee,zoo) func(whiz,car) func(herp,foobar)   func(10,8)
</code></pre>

<p>I've started with this: </p>

<pre><code>for r1 in df1.iterrows():
    for r2 in df2.iterrows():
        for c1 in r1:
            for c2 in r2:
</code></pre>

<p>but am not sure what to do with it, and would appreciate some help. </p>

<p>So to continue the discussion in the comments, you can use vectorization, which is one of the selling points of a library like pandas or numpy. Ideally, you shouldn't ever be calling <code>iterrows()</code>. To be a little more explicit with my suggestion:</p>

<pre><code># with df1 and df2 provided as above, an example
df3 = df1['A'] * 3 + df2['A']

# recall that df2 only has the one row so pandas will broadcast a NaN there
df3
0    foofoofoozoo
1             NaN
Name: A, dtype: object

# more generally

# we know that df1 and df2 share column names, so we can initialize df3 with those names
df3 = pd.DataFrame(columns=df1.columns) 
for colName in df1:
    df3[colName] = func(df1[colName], df2[colName]) 
</code></pre>

<p>Now, you could even have different functions applied to different columns by, say, creating lambda functions and then zipping them with the column names:</p>

<pre><code># some example functions
colAFunc = lambda x, y: x + y
colBFunc = lambda x, y; x - y
....
columnFunctions = [colAFunc, colBFunc, ...]

# initialize df3 as above
df3 = pd.DataFrame(columns=df1.columns)
for func, colName in zip(columnFunctions, df1.columns):
    df3[colName] = func(df1[colName], df2[colName])
</code></pre>

<p>The only "gotcha" that comes to mind is that you need to be sure that your function is applicable to the data in your columns. For instance, if you were to do something like <code>df1['A'] - df2['A']</code> (with df1, df2 as you have provided), that would raise a <code>ValueError</code> as the subtraction of two strings is undefined. Just something to be aware of. </p>

<hr>

<p><strong>Edit, re: your comment:</strong> That is doable as well. Iterate over the dfX.columns that is larger, so you don't run into a <code>KeyError</code>, and throw an <code>if</code> statement in there:</p>

<pre><code># all the other jazz
# let's say df1 is [['A', 'B', 'C']] and df2 is [['A', 'B', 'C', 'D']]
# so iterate over df2 columns
for colName in df2:
    if colName not in df1:
        df3[colName] = np.nan # be sure to import numpy as np
    else:
        df3[colName] = func(df1[colName], df2[colName])  
</code></pre>

python pandas dataframe iterator iteration