2013-09-05 8 views
6

Ho un df con migliaia di ticker per diversi contratti futuri. Hanno il nome abbreviato (che compare in seguito) e il nome lungo (che voglio avere in altri df)Metodo di tipo VLookup in R

full_list <- structure(
    list(
    Ticker = c("AC", "AIC", "BBS", "BO", "C", "DF"), 
    Long_Name = c("Ethanol -- CBOT", "DJ UBS Commodity Index -- CBOT", "South American Soybeans -- CBOT", "Soybean Oil -- CBT", "Corn -- CBT", "Dow Jones Industrial Average -- CBT") 
), 
    .Names = c("Ticker", "Long_Name"), 
    row.names = c(NA, 6L), 
    class = "data.frame" 
) 

Questa df ha l'elenco che ricevo tutti i giorni. Devo andare a cercare il nome abbreviato e abbinarlo al nome lungo.

replace <- structure(
    list(
    Type = c("F", "F", "F", "F", "F", "F"), 
    Location = c("US", "US", "US", "US", "US", "US"), 
    Symbol = c("BO", "C", "DF", "AIC", "AC", "BBS"), 
    Month = c("V13", "U13", "U13", "U13", "U13", "U13") 
), 
    .Names = c("Type", "Location", "Symbol", "Month"), 
    row.names = c(NA, 6L), 
    class = "data.frame" 
) 

Quello che sto cercando di R fare è prendere sostituire $ colonna Simbolo e trovare quei valori in full_list colonna $ Ticker e aggiungere una colonna, sostituire $ Long_Name, dove il rispettivo full_list $ Long_Name viene copiato. Spero che questo abbia un senso. Capisco che i nomi delle colonne siano difficili da seguire.

Questo sarebbe un facile VLookup in Excel ma ho uno script che ho userà quotidianamente quasi completato in R.

risposta

16

merge loro:

> merge(full_list, replace, by.x="Ticker", by.y="Symbol") 
    Ticker       Long_Name Type Location Month 
1  AC      Ethanol -- CBOT F  US U13 
2 AIC  DJ UBS Commodity Index -- CBOT F  US U13 
3 BBS  South American Soybeans -- CBOT F  US U13 
4  BO     Soybean Oil -- CBT F  US V13 
5  C       Corn -- CBT F  US U13 
6  DF Dow Jones Industrial Average -- CBT F  US U13 
+0

Questo metodo funziona se sono presenti "ticker" duplicati? userà il "long_name" più di una volta. – Tim

+0

@Tim: Sì: 'unione (full_list, rbind (replace, transform (replace, Month =" Z13 ")), by.x =" Ticker ", by.y =" Simbolo ")'. –

8

Si potrebbe utilizzare match - che dà l'indice di dove il primo argomento cade nel secondo argomento. Per esempio:

arg1 <- c("red","blue") 
arg2 <- c("blue","red") 

> match(arg1,arg2) 
[1] 2 1 

Poi basta creare una nuova colonna nel sostituire i frame di dati (nota - si dovrebbe chiamare in un altro modo, perché sostituire è in realtà una funzione in r) utilizzando la cornice di dati full_list con i simboli corrispondenti.

replace$Long_Name <- full_list$Long_Name[match(replace$Symbol,full_list$Ticker)] 

> replace 
    Type Location Symbol Month       Long_Name 
1 F  US  BO V13     Soybean Oil -- CBT 
2 F  US  C U13       Corn -- CBT 
3 F  US  DF U13 Dow Jones Industrial Average -- CBT 
4 F  US AIC U13  DJ UBS Commodity Index -- CBOT 
5 F  US  AC U13      Ethanol -- CBOT 
6 F  US BBS U13  South American Soybeans -- CBOT 
+0

È possibile abbinare su due criteri? Come se 'Long_Name' variava in base all'anno, è possibile aggiungere un argomento' $ year' in 'match'? –

+1

@RafaelMartins Vorrei esaminare il pacchetto 'data.table'. È possibile eseguire l'unione su chiavi a più colonne che sia facile e molto efficiente. Puoi anche usare 'unisci' e fornire un vettore di nomi di colonne ai parametri 'by'. Vedi: http://stackoverflow.com/questions/6709151/how-do-i-combine-two-data-frames-based-on-two-columns – dayne

6

Se si tratta di un grande set di dati si può beneficiare di una ricerca di ambiente:

library(qdap) 
replace$Long_Name <- lookup(replace$Symbol, full_list) 

## > replace 
## Type Location Symbol Month       Long_Name 
## 1 F  US  BO V13     Soybean Oil -- CBT 
## 2 F  US  C U13       Corn -- CBT 
## 3 F  US  DF U13 Dow Jones Industrial Average -- CBT 
## 4 F  US AIC U13  DJ UBS Commodity Index -- CBOT 
## 5 F  US  AC U13      Ethanol -- CBOT 
## 6 F  US BBS U13  South American Soybeans -- CBOT 
1

Se stai usando un grande insieme di dati, si potrebbe incorrere in alcuni problemi di tempo/memoria, se è questo il caso, provate questo:

require(plyr) 

colnames(replace)<-c("Type", "Location", "Ticker", "Month") 

Full<-join(full_list, replace, by = "Ticker", type = "left", match = "all") 

> Full 
    Ticker       Long_Name Type Location Month 
1  AC      Ethanol -- CBOT F  US U13 
2 AIC  DJ UBS Commodity Index -- CBOT F  US U13 
3 BBS  South American Soybeans -- CBOT F  US U13 
4  BO     Soybean Oil -- CBT F  US V13 
5  C       Corn -- CBT F  US U13 
6  DF Dow Jones Industrial Average -- CBT F  US U13 

Sebbene la sua più di una soluzione di una riga, fondere può richiedere un certo tempo per elaborare con dataframes grandi. Inoltre, il pacchetto plyr può essere il tuo migliore amico.

5

obbligatorio data.table risposta

library(data.table) 
full_list <- data.table(full_list, key='Symbol') 
replace <- data.table(replace, key='Ticker') 

replace[full_list] 

FWIW su un insieme di dati sopra le righe su un 1E5 digitato data.table sarà significativamente più veloce rispetto agli altri approcci elencati (tranne che per la versione qdap, non ho provato). merge timings can be found here