I’m trying to use a Currency Converter function (custom function) to convert amounts of each Order in a data table from one specific currency to another. I have two tables:
Ultimately, I need to convert all amounts for each order (Price, VAT, and Fees) from the “FromCUR” currency to the “ToCUR” currency associated with each order using the Exchange Rate table by matching the FromCUR field to the “From” field in the Exchange Rate table, and the same for the “ToCUR” with the “To” field to get the “Rate” and the “Action” type. Action will be used in the function to either Multiply or Divide the Amount from the Order by the Rate.
My complete code to re-produce the Function and tables is shown below.
Yet, I could not even manage to convert the Price as a start although I need to convert all amounts for each order. When I run the code, R throws the following error: “Error in switch(rate$Action, Multiply = Amount * rate$Rate, Divide = Amount/rate$Rate, : EXPR must be a length 1 vector”
I’m aware that .SDCols might help here, but not sure how to use it either.
Would be grateful if someone can fix the code or suggest an alternative more efficient one. Thanks.
CurConverter <- function(FromCUR, ToCUR, Amount, exchange_rate_table) {
# Look up exchange rate from the provided table
rate <- exchange_rate_table[From == FromCUR & To == ToCUR, .(Rate, Action)]
# if (nrow(rate) == 0) {
# warning("Exchange rate not found for the specified currencies. Returning original amount.")
# return(Amount)
# }
result <- switch(rate$Action,
Multiply = Amount * rate$Rate,
Divide = Amount / rate$Rate,
Amount) |>
as.numeric()
return(result)
}
# Example data tables
dfOrders <- data.table(
OrderID=c("A","B","C"),
FromCUR = c("USD", "AED", "GBP"),
ToCUR = c("EUR", "USD", "USD"),
Price = c(100, 200, 150),
VAT=c(10,20,15),
Fees=c(1,2,3)
)
dfXRate <- data.table(
From = c("USD", "AED", "GBP"),
To = c("EUR", "USD", "USD"),
Rate = c(1.06, 3.6725, 1.25),
Action = c("Multiply", "Divide", "Divide")
)
# Merge data tables based on currency columns
merged_df <- merge(dfOrders, dfXRate, by.x = c("FromCUR", "ToCUR"), by.y = c("From", "To"), all.x = TRUE)
# Apply the CurConverter function to each row
merged_df[, ConvertedPrice := CurConverter(FromCUR, ToCUR, Price, dfXRate)]
Here is how I would do it:
library(data.table)
convertCurrenciesWithSymbol <- function(orders, exchangeRates) {
# Merge orders with exchange rates
mergedData <- merge(orders, exchangeRates, by.x = c("FromCUR", "ToCUR"), by.y = c("From", "To"), all.x = TRUE)
# currency conversion
mergedData[, Converted := fifelse(Action == "Multiply" & ToCUR == "EUR",
paste0(as.character(round(Price * Rate, 2)), " €"),
fifelse(Action == "Divide" & ToCUR == "USD",
paste0(as.character(round(Price / Rate, 2)), " $"),
paste0("No Change, Original: ", Price)
)
)]
return(mergedData)
}
convertedOrders <- convertCurrencies(dfOrders, dfXRate)
convertedOrders
switch
library(data.table)
convertCurrenciesWithSwitch <- function(orders, exchangeRates) {
# Merge orders and rates
mergedData <- merge(orders, exchangeRates, by.x = c("FromCUR", "ToCUR"), by.y = c("From", "To"), all.x = TRUE)
# Define a helper function for conversion
convertWithSwitch <- function(action, toCurrency, price, rate) {
caseKey <- paste(action, toCurrency)
switch(caseKey,
"Multiply EUR" = paste0(as.character(round(price * rate, 2)), " €"),
"Divide USD" = paste0(as.character(round(price / rate, 2)), " $"),
paste0("No Change, Original: ", price))
}
# Currency conversion
mergedData[, Converted := mapply(convertWithSwitch, Action, ToCUR, Price, Rate)]
return(mergedData)
}
convertedOrdersWithSwitch <- convertCurrenciesWithSwitch(dfOrders, dfXRate)
convertedOrdersWithSwitch
FromCUR ToCUR OrderID Price VAT Fees Rate Action Converted
1: AED USD B 200 20 2 3.6725 Divide 54.46 $
2: GBP USD C 150 15 3 1.2500 Divide 120 $
3: USD EUR A 100 10 1 1.0600 Multiply 106 €