将VBA代码转换为R代码的问题

时间:2019-10-11 06:39:25

标签: r vba loops if-statement nested

我必须将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 obs。和> 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 个答案:

答案 0 :(得分:1)

这是使用dplyrtidyr的方法:

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

答案 1 :(得分:0)

使用shopt -s extglob mv -v "$PWD"/!(.git) "$PWD/NewDir" 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