pythonpython-3.xjoinpandasmerge

Merging multiple dataframes with non unique indexes


Given two DFs with non unique indexes and multidimentional columns:

ars:

           arsenal   arsenal   arsenal   arsenal
NaN             B3        SK        BX        BY
2015-04-15     NaN       NaN       NaN      26.0
2015-04-14     NaN       NaN       NaN       NaN
2015-04-13    26.0      26.0      23.0       NaN
2015-04-13    22.0      21.0      19.0       NaN

che:

           chelsea   chelsea   chelsea   chelsea
NaN             B3        SK        BX        BY
2015-04-15     NaN       NaN       NaN      1.01
2015-04-14    1.02       NaN       NaN       NaN
2015-04-14     NaN      1.05       NaN       NaN

here in csv format

,arsenal,arsenal,arsenal,arsenal
,B3,SK,BX,BY
2015-04-15,,,,26.0
2015-04-14,,,,
2015-04-13,26.0,26.0,23.0,
2015-04-13,22.0,21.0,19.0,

,chelsea,chelsea,chelsea,chelsea
,B3,SK,BX,BY
2015-04-15,,,,1.01
2015-04-14,1.02,,,
2015-04-14,,1.05,,

I would like to join/merge them, sort of an outer join so that rows are not dropped.

I would like the output to be:

            arsenal  arsenal   arsenal   arsenal chelsea   chelsea   chelsea   chelsea
NaN             B3        SK        BX        BY      B3        SK        BX        BY
2015-04-15     NaN       NaN       NaN      26.0     NaN       NaN       NaN      1.01
2015-04-14     NaN       NaN       NaN       NaN    1.02       NaN       NaN       NaN
2015-04-14     NaN       NaN       NaN       NaN     NaN      1.05       NaN       NaN
2015-04-13    26.0      26.0      23.0       NaN     NaN       NaN       NaN       NaN
2015-04-13    22.0      21.0      19.0       NaN     NaN       NaN       NaN       NaN

None of the pandas tools I know worked: merge, join, concat. merge's outer join gives a dot product which is not what I am looking for, while concat can't handle non unique indexes.

Do you have any ideas how this can be achieved?

Note: the lengths of dataframes won't be idential.


Solution

  • I've managed to sort it out using pandas' concat method.

    First, we need to add a Multiindex level so that it becomes unique:

    ars = pd.read_csv("ars.csv", index_col=[0], header=[0,1])
    che = pd.read_csv("che.csv", index_col=[0], header=[0,1])
    
    ars.index.name = "date"
    ars["num"] = range(0, len(ars.index))
    ars = ars.set_index("num", append=True)
    
    che.index.name = "date"
    che["num"] = range(0, len(che.index))
    che = che.set_index("num", append=True)
    

    Now we can use concat:

    df = pd.concat([ars, che], axis=1)
    df = df.reset_index()
    df = df.sort_index(by=["date", "num"], ascending=[False, True])
    df = df.set_index(["date", "num"])
    df.index = df.index.droplevel(1)
    

    Output:

                    arsenal             chelsea                
                    B3  SK  BX  BY      B3    SK  BX    BY
    date                                                  
    2015-04-15     NaN NaN NaN  26     NaN   NaN NaN  1.01
    2015-04-14     NaN NaN NaN NaN    1.02   NaN NaN   NaN
    2015-04-14     NaN NaN NaN NaN     NaN  1.05 NaN   NaN
    2015-04-13      26  26  23 NaN     NaN   NaN NaN   NaN
    2015-04-13      22  21  19 NaN     NaN   NaN NaN   NaN