我对R来说很陌生,而且我目前正在应用我对R必须进行分析工作的一点知识。
我有两个数据框 - 数据框A包含交易详情,而数据框B包含各种货币的每月结算汇率。
数据框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
的新列。我希望通过将数据框A中的COLLECTION_CRNCY
和MMYYYY
与数据框B相匹配来查看数据框B来获得此汇率值。即:
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
我可以使用vlookup和匹配通过Excel轻松完成此操作,但我想知道如何使用R来实现相同的结果,因为我的交易详细信息文件非常庞大。
答案 0 :(得分: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
类列上合并(暂时),因此您需要先将其取消分类< / p>
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 :(得分:1)
您可以使用R
和apply
使用基础merge
来解决此问题。
要解决问题,
<强> 1 强>
要合并数据,只需使用:
merge(dfa, dfb, by="MMYYYY")
2
要提取相关字段,我们可以按行方式使用apply函数。
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
答案 2 :(得分: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
答案 3 :(得分: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