2015-07-12 100 views
3

我對R很新,而且我現在正在申請,但是我不得不爲了工作而進行一項分析工作。Vlookup-match like功能在R

我有兩個數據框 - 數據框A由交易詳情組成,而數據框B由各種貨幣的月結賬匯率組成。

數據幀 - 交易明細

TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY LODG_DATE 
1   0001    INR   305000 Mar 2014 2014-03-01 
2   0002    USD   15000 Oct 2014 2014-10-31 
3   0003    JPY   85000 Feb 2015 2015-02-09 
4   0004    CNY  1800000 Mar 2015 2015-03-27 

structure(list(TRANSACTION_ID = c("0001", "0002", "0003", "0004"), 
COLLECTION_CRNCY = c("INR", "USD", "JPY", "CNY"), COLLECTION_AMT = c(305000, 
15000, 85000, 1800000), MMYYYY = structure(c(2014.16666666667, 
2014.75, 2015.08333333333, 2015.16666666667), class = "yearmon"), 
LODG_DATE = structure(c(16130, 16374, 16475, 16521), class = "Date")), 
row.names = c(NA, -4L), class = "data.frame") 

數據幀B - 匯率

MMYYYY  Date CNY INR  JPY  USD 
1 Mar 2014 2014-03-31 4.9444 47.726 82.0845 0.7951654 
2 Oct 2014 2014-10-31 4.7552 47.749 87.2604 0.7778469 
3 Feb 2015 2015-02-27 4.5990 45.222 87.7690 0.7338372 
4 Mar 2015 2015-03-31 4.5179 45.383 87.5395 0.7287036 

structure(list(MMYYYY = structure(c(2014.16666666667, 
2014.75, 2015.08333333333, 2015.16666666667), class = "yearmon"), 
Date = structure(c(16160, 16374, 16493, 16525), class = "Date"), CNY = 
c(4.9444, 4.7552, 4.599, 4.5179), INR = c(47.726, 47.749, 45.222, 45.383), 
JPY = c(82.0845, 87.2604, 87.769, 87.5395), USD = c(0.795165394, 0.77784692, 
0.733837235, 0.728703636)), .Names = c("MMYYYY", "Date", "CNY", "INR", "JPY", 
"USD"), class = "data.frame", row.names = c(NA, -4L)) 

我想什麼做的是建立在數據幀中的一個新列可能命名爲Exchange Rate。而且我想通過查找到數據幀B到得到這個匯率值,通過在數據幀的COLLECTION_CRNCYMMYYYY匹配數據幀BIE:

TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY LODG_DATE exchange.rate 
1   0001    INR   305000 Mar 2014 2014-03-01 47.7260000 
2   0002    USD   15000 Oct 2014 2014-10-31  0.7778469 
3   0003    JPY   85000 Feb 2015 2015-02-09 87.7690000 
4   0004    CNY  1800000 Mar 2015 2015-03-27  4.5179000 

我可以通過Excel中使用VLOOKUP很容易地做到這一點,匹配,但我想知道如何使用R來實現相同的結果,因爲我的交易細節文件非常龐大。

+1

正如一般性意見:與R數據的操作,這是更好地認爲,在數據庫方面,而不是Excel的條款。你想要做的是一個連接,可以在R中以各種方式完成。 –

回答

4

以下是可能的data.table方法。基本上你需要做的是df2轉換爲長格式,然後只是簡單的(二進制)左加入到df1

library(data.table) 
temp <- melt(setDT(df2[-2]), "MMYYYY", variable.name = "COLLECTION_CRNCY") 
setkey(setDT(df1), MMYYYY, COLLECTION_CRNCY)[temp, exchange.rate := i.value] 
df1 
# TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY LODG_DATE exchange.rate 
# 1:   0001    INR   305000 2014.167 2014-03-01 47.7260000 
# 2:   0002    USD   15000 2014.750 2014-10-31  0.7778469 
# 3:   0003    JPY   85000 2015.083 2015-02-09 87.7690000 
# 4:   0004    CNY  1800000 2015.167 2015-03-27  4.5179000 

或者,你可以使用「Hadleyverse」但dplyr類似的事情將無法合併上zoo班列(現在),所以你需要unclass他們先

library(dplyr) 
library(tidyr) 
df2[-2] %>% 
    gather(COLLECTION_CRNCY, exchange.rate, -MMYYYY) %>% 
    mutate(MMYYYY = as.numeric(MMYYYY)) %>% 
    left_join(df1 %>% mutate(MMYYYY = as.numeric(MMYYYY)), ., 
          by = c("MMYYYY", "COLLECTION_CRNCY")) 
# TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY LODG_DATE exchange.rate 
# 1   0001    INR   305000 2014.167 2014-03-01 47.7260000 
# 2   0002    USD   15000 2014.750 2014-10-31  0.7778469 
# 3   0003    JPY   85000 2015.083 2015-02-09 87.7690000 
# 4   0004    CNY  1800000 2015.167 2015-03-27  4.5179000 
1

您可以通過使用apply和使用基本R解決這個問題。

打破了這種問題,

  1. 兩個數據集融合在一起
  2. 提取相關的列

要簡單地將數據合併使用:

merge(dfa, dfb, by="MMYYYY")

提取相關領域,我們可以使用的應用功能,以橫行方式。

apply(df, 1, function(x) ...)

其中df是data.frame,1信號橫行。


全部放在一起,我們可以在一個行解壓縮匯率這樣的:

dfa$exchange.rate <- apply(df, 1, function(x) x[x[['COLLECTION_CRNCY']]])

什麼線x[x[['COLLECTION_CRNCY']]]正在做的是簡單地查找列COLLECTION_CRNCY,然後使用該值來查詢適當的貨幣列。


最終代碼:

dfa$exchange.rate <- apply(merge(dfa, dfb, by="MMYYYY"), 1, function(x) x[x[['COLLECTION_CRNCY']]]) 
dfa$exchange.rate <- as.numeric(dfa$exchange.rate) # since it isn't numeric format. 
# TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY LODG_DATE exchange.rate 
# 1   0001    INR   305000 2014.167 2014-03-01 47.7260000 
# 2   0002    USD   15000 2014.750 2014-10-31  0.7778469 
# 3   0003    JPY   85000 2015.083 2015-02-09 87.7690000 
# 4   0004    CNY  1800000 2015.167 2015-03-27  4.5179000 
0

從廣角到轉型長格式可以reshape()完成。它可能是R中最令人討厭的功能,但如果您足夠長時間地使用它的選項,通常可以到達想要去的地方。一旦您使用長格式的B,只需致電merge()即可獲得所需的輸出。供參考

B.id <- c('MMYYYY','Date'); 
B.time <- setdiff(names(B),B.id); 
B.long <- reshape(B,dir='l',idvar=B.id,varying=B.time,times=B.time,timevar='COLLECTION_CRNCY',v.names='exchange.rate',new.row.names=1:(length(B.time)*nrow(B))); 
B.long; 
##  MMYYYY  Date COLLECTION_CRNCY exchange.rate 
## 1 2014.167 2014-03-31    CNY  4.9444000 
## 2 2014.750 2014-10-31    CNY  4.7552000 
## 3 2015.083 2015-02-27    CNY  4.5990000 
## 4 2015.167 2015-03-31    CNY  4.5179000 
## 5 2014.167 2014-03-31    INR 47.7260000 
## 6 2014.750 2014-10-31    INR 47.7490000 
## 7 2015.083 2015-02-27    INR 45.2220000 
## 8 2015.167 2015-03-31    INR 45.3830000 
## 9 2014.167 2014-03-31    JPY 82.0845000 
## 10 2014.750 2014-10-31    JPY 87.2604000 
## 11 2015.083 2015-02-27    JPY 87.7690000 
## 12 2015.167 2015-03-31    JPY 87.5395000 
## 13 2014.167 2014-03-31    USD  0.7951654 
## 14 2014.750 2014-10-31    USD  0.7778469 
## 15 2015.083 2015-02-27    USD  0.7338372 
## 16 2015.167 2015-03-31    USD  0.7287036 
merge(A,B.long[c('MMYYYY','COLLECTION_CRNCY','exchange.rate')],all.x=T); 
## COLLECTION_CRNCY MMYYYY TRANSACTION_ID COLLECTION_AMT LODG_DATE exchange.rate 
## 1    CNY 2015.167   0004  1800000 2015-03-27  4.5179000 
## 2    INR 2014.167   0001   305000 2014-03-01 47.7260000 
## 3    JPY 2015.083   0003   85000 2015-02-09 87.7690000 
## 4    USD 2014.750   0002   15000 2014-10-31  0.7778469 
1

另一種方式:

res <- numeric(nrow(dfA)) 
for(i in seq_len(nrow(dfA))) { 
    res[i] <- dfB[match(dfA$MMYYYY[i], dfB$MMYYY), 
        match(dfA$COLLECTION_CRNCY[i], names(dfB))]} 
dfA$Exchange<- res 
# TRANSACTION_ID COLLECTION_CRNCY COLLECTION_AMT MMYYYY 
# 1   0001    INR   305000 2014.167 
# 2   0002    USD   15000 2014.750 
# 3   0003    JPY   85000 2015.083 
# 4   0004    CNY  1800000 2015.167 
# LODG_DATE Exchange 
# 1 2014-03-01 47.7260000 
# 2 2014-10-31 0.7778469 
# 3 2015-02-09 87.7690000 
# 4 2015-03-27 4.5179000