2015-07-12 2 views
3

Я очень новичок в R, и в настоящее время я применяю хотя бы небольшое знание R, которое у меня есть для аналитической работы, которую я должен выполнить для работы.Vlookup-match like function in R

У меня есть два блока данных - dataframe A состоит из данных транзакций, а dataframe B состоит из ежемесячного обменного курса для разных валют. рамка

Data A - сделка подробности

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)) 

То, что я хотел бы сделать, это создать новый столбец в кадре данных A возможно, названный Exchange Rate. И я хотел бы получить это значение обменного курса путем поиска для кадра данных B, путем сопоставления COLLECTION_CRNCY и MMYYYY в данном кадре А до кадра данных МОВ:

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 с помощью ВПРА и но я хотел бы знать, как я могу добиться достижения тех же результатов, что и 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

вы могли бы решить эту проблему, используя базу R с помощью apply и merge.

Чтобы сломать эту проблему,

  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