2015-12-03 3 views
4

J'ai 3 DataFrames qui ont un nombre différent d'index partagés. Par exemple:Rejoindre des données Pandas sur des index partagés

>>> df0=pd.DataFrame(index=pd.MultiIndex.from_product([[1,2,3,4],[2011,2012],['A','B']], names=['Season','Year','Location'])) 
>>> df0['Value0']=np.random.randint(1,100,len(df0)) 
>>> 
>>> df1=pd.DataFrame(index=pd.MultiIndex.from_product([[2011,2012],['A','B']], names=['Year','Location'])) 
>>> df1['Value1']=np.random.randint(1,100,len(df1)) 
>>> 
>>> df2=pd.DataFrame(index=['A','B']) 
>>> df2.index.name='Location' 
>>> df2['Value2']=np.random.randint(1,100,len(df2)) 
>>> df0 
         Value0 
Season Year Location   
1  2011 A    18 
      B    63 
     2012 A    88 
      B    30 
2  2011 A    35 
      B    60 
     2012 A    61 
      B    4 
3  2011 A    70 
      B    9 
     2012 A    11 
      B    38 
4  2011 A    68 
      B    57 
     2012 A    13 
      B    35 
>>> df1 
       Value1 
Year Location   
2011 A    22 
    B    74 
2012 A    73 
    B    44 
>>> df2 
      Value2 
Location   
A    70 
B    85 
>>> 

Je suis à la recherche de la meilleure façon de les rejoindre sur leurs index communs.

choses que j'ai essayé:

1) pd.concat([df0,df1,df2],1) serait bien car il accepte une liste de dataframes, mais cela semble fonctionner que si les dataframes ont le même nombre d'indices.

2) Rejoindre l'une des bases de données multi-index avec l'index unique DataFrame fonctionne: df1.join(df2) ou df0.join(df2). Cependant se joindre à la DataFrame avec deux indices avec les DataFrame avec trois indices ne: df0.join(df1) et me donne l'erreur suivante: « NotImplementedError: la fusion avec plus d'un chevauchement de niveau sur un multi-index n'est pas mis en œuvre »

À ce stade , l'approche que j'ai prise est de réinitialiser les index et d'utiliser pd.merge(). Voir ci-dessous:

def JoinMulti(DFList): 
    FinalDF=DFList[0].reset_index() 
    for OtherDF in DFList[1:]: 
     FinalDF=pd.merge(FinalDF, OtherDF.reset_index(), how='outer') 

    #Now I want reindex it so that it's indexed the same as the `DataFrame` with the highest number of levels 
    NLevels=[x.index.nlevels for x in DFList] 
    MaxIndexPos=NLevels.index(max(NLevels)) 
    FinalIndex=DFList[MaxIndexPos].index 
    FinalDF=FinalDF.set_index(FinalIndex.names).reindex(FinalIndex) 
    return FinalDF 

>>> JoinMulti([df0,df1,df2]) 
         Value0 Value1 Value2 
Season Year Location       
1  2011 A    43  5  96 
      B    63  46  97 
     2012 A    68  6  96 
      B    23  99  97 
2  2011 A    66  5  96 
      B    30  46  97 
     2012 A    45  6  96 
      B    79  99  97 
3  2011 A    66  5  96 
      B    21  46  97 
     2012 A    86  6  96 
      B    11  99  97 
4  2011 A    95  5  96 
      B    58  46  97 
     2012 A    32  6  96 
      B    80  99  97 
>>> 

Est-ce une approche raisonnable? Y a-t-il des améliorations qui pourraient être apportées ou des exceptions que j'oublie?

Répondre

0

I solution modifiée par Stefan Jansen:

def jez(df0,df1,df2): 
    df1 = df1.join(df2) 
    df0 = df0.reset_index('Season') 
    FinalDF = df0.join(df1).set_index('Season', append=True).reorder_levels(['Season', 'Year', 'Location']).sortlevel() 
    return FinalDF 

print jez(df0,df1,df2) 

Durée:

In [41]: %timeit jez(df0,df1,df2) 
The slowest run took 4.14 times longer than the fastest. This could mean that an intermediate result is being cached 
100 loops, best of 3: 5.02 ms per loop 

In [42]: %timeit JoinMulti([df0,df1,df2]) 
100 loops, best of 3: 9.83 ms per loop