2012-12-18 2 views
6

J'ai un dataframe des trades boursiers historiques. Le cadre contient des colonnes telles que ['ticker', 'date', 'cusip', 'profit', 'security_type']. Dans un premier temps:Mise à jour de pandas DataFrame par clé

trades['cusip'] = np.nan 
trades['security_type'] = np.nan 

J'ai des fichiers de configuration historiques que je peux charger dans des cadres qui ont des colonnes comme [ 'ticker', 'CUSIP', 'date', 'nom', '-sécurité', 'primary_exchange'].

Je voudrais mettre à jour le cadre des métiers avec le cusip et security_type de config, mais seulement où le ticker et la date correspondent.

Je pensais que je pouvais faire quelque chose comme:

pd.merge(trades, config, on=['ticker', 'date'], how='left') 

Mais cela ne met pas à jour les colonnes, il ajoute que les colonnes de configuration aux métiers.

Les travaux suivants, mais je pense qu'il doit y avoir une meilleure façon. Sinon, je vais probablement le faire en dehors des pandas.

for date in trades['date'].unique(): 
    config = get_config_file_as_df(date) 
    ## config['date'] == date 
    for ticker in trades['ticker'][trades['date'] == date]: 
     trades['cusip'][ 
          (trades['ticker'] == ticker) 
         & (trades['date'] == date) 
         ] \ 
      = config['cusip'][config['ticker'] == ticker].values[0] 

     trades['security_type'][ 
          (trades['ticker'] == ticker) 
         & (trades['date'] == date) 
         ] \ 
      = config['security_type'][config['ticker'] == ticker].values[0] 

Répondre

13

Supposons que vous ayez cette configuration:

import pandas as pd 
import numpy as np 
import datetime as DT 

nan = np.nan 

trades = pd.DataFrame({'ticker' : ['IBM', 'MSFT', 'GOOG', 'AAPL'], 
         'date' : pd.date_range('1/1/2000', periods = 4), 
         'cusip' : [nan, nan, 100, nan] 
         }) 
trades = trades.set_index(['ticker', 'date']) 
print(trades) 
#     cusip 
# ticker date    
# IBM 2000-01-01 NaN 
# MSFT 2000-01-02 NaN 
# GOOG 2000-01-03 100 # <-- We do not want to overwrite this 
# AAPL 2000-01-04 NaN 

config = pd.DataFrame({'ticker' : ['IBM', 'MSFT', 'GOOG', 'AAPL'], 
         'date' : pd.date_range('1/1/2000', periods = 4), 
         'cusip' : [1,2,3,nan]}) 
config = config.set_index(['ticker', 'date']) 

# Let's permute the index to show `DataFrame.update` correctly matches rows based on the index, not on the order of the rows. 
new_index = sorted(config.index) 
config = config.reindex(new_index)  
print(config) 
#     cusip 
# ticker date    
# AAPL 2000-01-04 NaN 
# GOOG 2000-01-03  3 
# IBM 2000-01-01  1 
# MSFT 2000-01-02  2 

Ensuite, vous pouvez mettre à jour les valeurs NaN en trades avec des valeurs de config selon la méthode DataFrame.update. Notez que DataFrame.update correspond à des lignes basées sur des index (c'est pourquoi set_index a été appelé ci-dessus).

trades.update(config, join = 'left', overwrite = False) 
print(trades) 

#     cusip 
# ticker date    
# IBM 2000-01-01  1 
# MSFT 2000-01-02  2 
# GOOG 2000-01-03 100 # If overwrite = True, then 100 is overwritten by 3. 
# AAPL 2000-01-04 NaN