2017-10-10 3 views
1

J'ai 2 données avec la colonne 0 pour 'Date'.Fusionner 2 données sur la date antérieure la plus proche

Il existe plus de dates secondaires que de dates principales et elles sont différentes (bien que proches dans le temps). Je souhaite fusionner les deux données en conservant les dates principales comme référence et en choisissant les dates secondaires (lignes) à fusionner en fonction de la date immédiate avant la date principale.

main = pd.DataFrame({'Date':pd.to_datetime(
     ['2013-07-23', '2013-10-28', '2014-01-27', '2014-04-23', 
     '2014-07-22', '2014-10-20', '2015-01-27', '2015-04-27', 
     '2015-07-21', '2015-10-27', '2016-01-26', '2016-04-26', '2016-07-26']) }) 

     Date 
0 2013-07-23 
1 2013-10-28 
2 2014-01-27 
3 2014-04-23 
4 2014-07-22 
5 2014-10-20 
6 2015-01-27 
7 2015-04-27 
8 2015-07-21 
9 2015-10-27 
10 2016-01-26 
11 2016-04-26 
12 2016-07-26 

Et

sec = pd.DataFrame({'Date':pd.date_range('2013-07-01',periods=42,freq='1MS')}) 

     Date 
0 2013-07-01 
1 2013-08-01 
2 2013-09-01 
3 2013-10-01 
... 

38 2016-09-01 
39 2016-10-01 
40 2016-11-01 
41 2016-12-01 

Les dates doivent être fusionnées avec cette logique, bien en ne conservant que date principale et le reste des colonnes pour les deux dataframes:

(tri inverse chronologique)

MERGED 
     Date Main Date Secondary 
0  2016-07-26 2016-07-01 
1  2016-04-26 2016-04-01 
2  2016-01-26 2016-01-01 
3  2015-10-27 2015-10-01 
4  2015-07-21 2015-07-01 
5  2015-04-27 2015-04-01 
6  2015-01-27 2015-01-01 
7  2014-10-20 2014-10-01 
8  2014-07-22 2014-07-01 
9  2014-04-23 2014-04-01 
10 2014-01-27 2014-01-01 
11 2013-10-28 2013-10-01 
12 2013-07-23 2013-07-01 

Les solutions que j'ai trouvées sont liées à la fusion de 2 dates qui sont les plus proches, mais pour ce cas, le plus proche pourrait signifier une date secondaire après la date principale qui viole la condition «passé».

Merge dataframe on closest date

Celui-ci semble similaire, mais je ne sais pas comment l'appliquer à mon cas.

How to merge two dataframes based on the closest (or most recent) timestamp

+0

'pd.merge_asof()' – DJK

+0

Merci @ djk47463! Je vois qu'il y a un paramètre tolérance = pd.Timedelta(), mais si je le comprends correctement il trouve la valeur la plus proche (pourrait être future). Comment l'établir vers le passé? – Diego

+0

Il fonctionne uniquement sur le passé le plus proche, regardez le paramètre 'allow_exact_matches' – DJK

Répondre

1

est ici un essai avec merge_asof:

df = pd.merge_asof(main.set_index('Date').sort_index(), 
        sec.set_index('Date',drop=False).sort_index(), 
        left_index=True, 
        right_index=True, 
        direction='backward') # backward is the default, so you 
              # can leave this out if you prefer 

df.rename(columns={'Date':'Date_sec'})\ 
    .sort_index(ascending=False).reset_index() 

Une note de syntaxe: La drop=False est nécessaire de veiller à ce que la date du dataframe secondaire est préservée. Sans cela, la base de données fusionnée ne contiendra que la date de la base de données principale.

Résultats:

  Date Date_sec 
0 2016-07-26 2016-07-01 
1 2016-04-26 2016-04-01 
2 2016-01-26 2016-01-01 
3 2015-10-27 2015-10-01 
4 2015-07-21 2015-07-01 
5 2015-04-27 2015-04-01 
6 2015-01-27 2015-01-01 
7 2014-10-20 2014-10-01 
8 2014-07-22 2014-07-01 
9 2014-04-23 2014-04-01 
10 2014-01-27 2014-01-01 
11 2013-10-28 2013-10-01 
12 2013-07-23 2013-07-01 
+0

Merci beaucoup, pour une raison quelconque, je reçois TypeError: merge_asof() a un argument mot-clé inattendu 'direction' – Diego

+0

@Diego vous avez probablement un ancien version des pandas. Je crois que 'direction' a été ajouté en 0.20.0, mais' backward' est la valeur par défaut, donc vous pouvez probablement juste laisser tomber. Je l'ai seulement ajouté ici pour plus de clarté, car il est parfois préférable d'être explicite avec des arguments de mots-clés, même si ce n'est pas nécessaire. – JohnE

+1

Vous avez raison! Pandas amélioré. Maintenant, je reçois TypeError: l'objet 'NoneType' n'est pas appelable sur right_index = True. Recherche, mais n'a pas pu trouver des indices ... – Diego