Эффективно конвертировать значения для каждой строки в другую валюту - PullRequest
3 голосов
/ 22 апреля 2020

Предположим, что эти два data.frames:

rates <- data.frame(Date = c("2000-01-01","2000-03-02","2000-03-25","2000-04-13"), Euro = c(1.2,1.27,1.4,1.6), Aussie = c(0.85,0.82,0.93,0.89))
toConvert <- data.frame(Date = c("2000-01-01","2000-03-02","2000-03-25","2000-04-13"), currency = c("Euro","Aussie","Euro","Aussie"),
                        Value1 = c(5,6,7,8), Value2 = c(10,15,23,85),Value3 = c(50,60,89,93))

Существует ли эффективный способ преобразования столбцов Value1, Value2 и Value3 в доллары с учетом ставок в таблице rates ?

По сути, код должен найти скорость на основе столбцов Date и currency в таблице toConvert и поделить Value1, Value2 и Value3 на соответствующую скорость в таблице rates.

Я уже пытался использовать for l oop, который работает, но работает вечно. (Имейте в виду, что это примеры таблиц. Фактическая таблица toConvert содержит 100 000 строк данных, а таблица rates содержит ежедневные данные за 1990 г.).

Что я пробовал:

for (i in 1:nrow(toConvert)) {
  rate <- as.numeric(rates[rates$Date == toConvert[i,]$Date, as.character(toConvert[1,]$currency)])
  toConvert[i,]$Value1 <- toConvert[i,]$Value1 / rate
  toConvert[i,]$Value2 <- toConvert[i,]$Value2 / rate
  toConvert[i,]$Value3 <- toConvert[i,]$Value3 / rate
}

Что занимает много времени, используя 100 тыс. Строк.

Ожидаемый результат:

    Date    currency   Value1    Value2    Value3
2000-01-01     Euro 4.166667  8.333333  41.66667
2000-03-02   Aussie 7.317073 18.292683  73.17073
2000-03-25     Euro 5.000000 16.428571  63.57143
2000-04-13   Aussie 8.988764 95.505618 104.49438

Ответы [ 4 ]

3 голосов
/ 22 апреля 2020

Я рекомендую вам взглянуть на пакет data.table , если у вас большой объем данных

library(data.table)

setDT(rates)
setDT(toConvert)

lrates <- melt(rates,id.vars = "Date")
toConvert[lrates,c("Value1", "Value2", "Value3"):=.SD/i.value,on=.(Date,currency=variable),.SDcols = c("Value1", "Value2", "Value3")]

toConvert
#>          Date currency   Value1    Value2    Value3
#> 1: 2000-01-01     Euro 4.166667  8.333333  41.66667
#> 2: 2000-03-02   Aussie 7.317073 18.292683  73.17073
#> 3: 2000-03-25     Euro 5.000000 16.428571  63.57143
#> 4: 2000-04-13   Aussie 8.988764 95.505618 104.49438

Создано в 2020-04-22 Представить пакет (v0.3.0)

1 голос
/ 22 апреля 2020

Использование tidyverse (dplyr и tidyr) для обработки всего data.frame в одном go.

rates <- data.frame(
  Date = c("2000-01-01","2000-03-02","2000-03-25","2000-04-13"), 
  Euro = c(1.2,1.27,1.4,1.6), 
  Aussie = c(0.85,0.82,0.93,0.89))
# Note I've added a capital C to "Currency" for consistency
toConvert <- data.frame(
  Date = c("2000-01-01","2000-03-02","2000-03-25","2000-04-13"), 
  Currency = c("Euro","Aussie","Euro","Aussie"),
  Value1 = c(5,6,7,8), Value2 = c(10,15,23,85), Value3 = c(50,60,89,93))


library("dplyr")
library("tidyr")

# Gathering the rate in a tidyer format
rates <- rates %>%
  tidyr::gather(Currency, Rate, Euro, Aussie)

rates
#>         Date Currency Rate
#> 1 2000-01-01     Euro 1.20
#> 2 2000-03-02     Euro 1.27
#> 3 2000-03-25     Euro 1.40
#> 4 2000-04-13     Euro 1.60
#> 5 2000-01-01   Aussie 0.85
#> 6 2000-03-02   Aussie 0.82
#> 7 2000-03-25   Aussie 0.93
#> 8 2000-04-13   Aussie 0.89

# Add the rate with a join - this is the trick
toConvert %>%
  left_join(rates, by = c("Date", "Currency")) %>% 
# From there it is easy to convert everything at once
  mutate_at(vars(starts_with("Value")), ~ .x / Rate)
#> Warning: Column `Currency` joining factor and character vector, coercing into
#> character vector
#>         Date Currency   Value1    Value2    Value3 Rate
#> 1 2000-01-01     Euro 4.166667  8.333333  41.66667 1.20
#> 2 2000-03-02   Aussie 7.317073 18.292683  73.17073 0.82
#> 3 2000-03-25     Euro 5.000000 16.428571  63.57143 1.40
#> 4 2000-04-13   Aussie 8.988764 95.505618 104.49438 0.89

Создано в 2020-04-22 с помощью пакета prepx (v0.3.0)

Вы можете игнорировать предупреждение при присоединении или исправить его, убедившись, что Currency является символьной проверкой, а не фактором (обычно используется stringsAsFactors = FALSE при загрузке данные).

0 голосов
/ 22 апреля 2020

Чистый раствор ...

library(dplyr)

tidy_rates <- rates %>% pivot_longer(cols = -c(Date), names_to = "currency", values_to = "rate")

toConvert %>% left_join(tidy_rates, by = c("Date" = "Date", "currency" = "currency")) %>% 
  mutate(
    value1_converted = Value1/rate,
    value2_converted = Value2/rate,
    value3_converted = Value3/rate
  )

вывод

enter image description here

0 голосов
/ 22 апреля 2020
#merge two files
ld <- melt(rates,id.vars = "Date")
library(data.table)
setDT(ld)
setDT(toConvert)
setnames(ld,c("variable","value"),c("currency","rate"))
s <- merge(toConvert,ld,all.x = TRUE,by=c("Date","currency"))
library(dplyr)
df <- s %>% mutate_at(vars(matches("Value")),funs(./rate)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...