You can use functools.reduce to iteratively apply pd.merge to each of the DataFrames:
result = functools.reduce(merge, dfs)
It is equivalent
result = dfs[0] for df in dfs[1:]: result = merge(result, df)
To pass the argument on=['org', 'name'] , you can use functools.partial define a merge function:
merge = functools.partial(pd.merge, on=['org', 'name'])
Since specifying the suffixes parameter in functools.partial would allow one fixed choice of suffix, and since we need a different suffix for each pd.merge , I think it would be easier to prepare a column of DataFrames names before calling pd.merge :
for i, df in enumerate(dfs, start=1): df.rename(columns={col:'{}_df{}'.format(col, i) for col in ('items', 'spend')}, inplace=True)
For instance,
import pandas as pd import numpy as np import functools np.random.seed(2015) N = 50 dfs = [pd.DataFrame(np.random.randint(5, size=(N,4)), columns=['org', 'name', 'items', 'spend']) for i in range(9)] for i, df in enumerate(dfs, start=1): df.rename(columns={col:'{}_df{}'.format(col, i) for col in ('items', 'spend')}, inplace=True) merge = functools.partial(pd.merge, on=['org', 'name']) result = functools.reduce(merge, dfs) print(result.head())
gives
org name items_df1 spend_df1 items_df2 spend_df2 items_df3 \ 0 2 4 4 2 3 0 1 1 2 4 4 2 3 0 1 2 2 4 4 2 3 0 1 3 2 4 4 2 3 0 1 4 2 4 4 2 3 0 1 spend_df3 items_df4 spend_df4 items_df5 spend_df5 items_df6 \ 0 3 1 0 1 0 4 1 3 1 0 1 0 4 2 3 1 0 1 0 4 3 3 1 0 1 0 4 4 3 1 0 1 0 4 spend_df6 items_df7 spend_df7 items_df8 spend_df8 items_df9 spend_df9 0 3 4 1 3 0 1 2 1 3 4 1 3 0 0 3 2 3 4 1 3 0 0 0 3 3 3 1 3 0 1 2 4 3 3 1 3 0 0 3