Проблема с переводом кода VBA в код R - PullRequest
0 голосов
/ 11 октября 2019

Мне нужно «перевести» код Excel VBA в код R. Я плохо знаком с программированием и мог бы немного помочь. Код VBA выглядит следующим образом:

lastrow = .UsedRange.Rows.Count
lastcolumn = .UsedRange.Columns.Count

Nominal = ThisWorkbook.Worksheets("Admin").Cells(15, 3)
Coupons = ThisWorkbook.Worksheets("Admin").Cells(16, 3)

       For a = 1 To lastcolumn
            If .Cells(1, a) = "X" Then
                For b = 2 To lastrow
                    For c = a + 1 To lastcolumn
                        If .Cells(b, a).Value = Year(Date) - 1 + c - a Then
                            .Cells(b, c).Value = .Cells(b, Nominal) + .Cells(b, Nominal) * .Cells(b, Coupons) / 100
                        ElseIf .Cells(b, a).Value > Year(Date) - 1 + c - a Then
                            .Cells(b, c).Value = .Cells(b, Nominal) * .Cells(b, Coupons) / 100
                        End If
                    Next
                    If .Cells(b, a) = vbEmpty Or .Cells(b, a) - Year(Date) > lastcolumn - a - 1 Then
                        .Cells(b, c - 1).Value = .Cells(b, Nominal)
                    End If
                Next
            Exit For
            End If
        Next
        MsgBox ("Hello World")

Первое условие If относится к столбцу с именем X, который отделяет «старые» столбцы с левой стороны от «новых» столбцов с правой стороны. Я могу предоставить вам некоторые данные, аналогичные данным, с которыми мне приходится работать в R.

data <- data.frame("nominal" = c(500000,1000000,2000000,1470000,500000,1000000), "coupon" = c(0,0,0,0.01,0.03,0.04), "year of maturity" = c(2023,2020,2019,2021,2022,2023), "X" = c(rep("X",6)))

Мой желаемый результат будет выглядеть так:

 data_final <- data.frame("nominal" = c(500000,1000000,2000000,1470000,500000,1000000), "coupon" = c(0,0,0,0.01,0.03,0.04), "year of maturity" = c(2023,2020,2019,2021,2022,2023), "X" = c(rep("X",6)) , "2019" = c(0,0,2000000,147,150,400), "2020" = c(0,1000000,0,147,150,400), "2021" = c(0,0,0,1470147,150,400), "2022" = c(0,0,0,0,500150,400), "2023" = c(500000,0,0,0,0,1000400))

Обратите внимание, что реальные данныенамного больше (> 2000 обс. и> 50 переменных [самый большой год погашения - 2068]), поэтому я должен использовать циклы. Моя попытка перевести код VBA выглядит следующим образом (нет необходимости в окне сообщения в R-коде):

year <- as.numeric(format(Sys.Date(), "%Y"))

for (a in 1:ncol(data)) {
 if (data[1,a] == "X") {
  for (b in 1:nrow(data)) {
    for (c in a+1:48) {
      if (data[b,a] == year - 1 + c - a) {
        data[b,c] <- data[b,"nominal"] + data[b,"nominal"]*data[b, "coupons"] / 100
      } else {
        data[b,c] <- data[b,"nominal"]*data[b, "coupons"] / 100
      }
      if (data[b,a] == is.na() | data[b,a] - jahr > nrow(data) - a - 1) {
        data[b,c-1] <- data[b, "nominal"]
      }
    }
  }
 }

}

Я либо получаю следующую ошибку, либо вообще ничего(что означает отсутствие предупреждения / ошибки, но также и результатов):

Error in matrix(unlist(value, recursive = FALSE, use.names = FALSE), nrow = nr,  : 'data' must be of a vector type, was 'NULL'

Обратите внимание, что я не разрешил использовать пакеты в качестве jrvFinance. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Вот подход с dplyr и tidyr:

library(dplyr); library(tidyr)
year <- as.numeric(format(Sys.Date(), "%Y"))
data %>%
  rowid_to_column() %>%  # Add a row to keep track of original order
  uncount(year.of.maturity - year + 1) %>%    # Make copy for each year until maturity
  group_by(nominal, coupon) %>%
  mutate(cur_year = year + row_number() - 1,  # Assign year number
         value =  nominal * (coupon/100 + if_else(cur_year == year.of.maturity,
                                              1, 0))) %>%   # debt service
  ungroup() %>%
  spread(cur_year, value, fill = 0)   # Convert year rows into year columns

## A tibble: 6 x 10
#  rowid nominal coupon year.of.maturity X      `2019`  `2020`  `2021` `2022`  `2023`
#  <int>   <dbl>  <dbl>            <dbl> <fct>   <dbl>   <dbl>   <dbl>  <dbl>   <dbl>
#1     1  500000   0                2023 X           0       0       0      0  500000
#2     2 1000000   0                2020 X           0 1000000       0      0       0
#3     3 2000000   0                2019 X     2000000       0       0      0       0
#4     4 1470000   0.01             2021 X         147     147 1470147      0       0
#5     5  500000   0.03             2022 X         150     150     150 500150       0
#6     6 1000000   0.04             2023 X         400     400     400    400 1000400
0 голосов
/ 11 октября 2019

Используя dplyr и tidyr вы можете сделать

library(dplyr)
library(tidyr)

year_max <- max(my_df$year.of.maturity)
year_start <- as.numeric(format(Sys.Date(), "%Y"))

my_df %>% 
  # For each combination create the year column from start to maximum year
  group_by(nominal, coupon, year.of.maturity, X) %>% 
  expand(year = year_start:year_max) %>%
  # Set value for each year
  mutate(value = case_when(year < year.of.maturity ~ nominal * coupon / 100, 
                           year == year.of.maturity ~ nominal + nominal * coupon / 100, 
                           TRUE ~ 0)) %>% 
  # Spread transforms the data from long to wide to have the desired representation
  spread(year, value) %>% 
  ungroup()

# A tibble: 6 x 9
#   nominal coupon year.of.maturity X      `2019`  `2020`  `2021` `2022`  `2023`
#     <dbl>  <dbl>            <dbl> <fct>   <dbl>   <dbl>   <dbl>  <dbl>   <dbl>
# 1  500000   0                2023 X           0       0       0      0  500000
# 2  500000   0.03             2022 X         150     150     150 500150       0
# 3 1000000   0                2020 X           0 1000000       0      0       0
# 4 1000000   0.04             2023 X         400     400     400    400 1000400
# 5 1470000   0.01             2021 X         147     147 1470147      0       0
# 6 2000000   0                2019 X     2000000       0       0      0       0

Данные

my_df <-
  data.frame("nominal" = c(500000, 1000000, 2000000, 1470000, 500000, 1000000),
             "coupon" = c(0, 0, 0, 0.01, 0.03, 0.04),
             "year of maturity" = c(2023, 2020, 2019, 2021, 2022, 2023),
             "X" = c(rep("X", 6)))
...