【问题标题】:R - Looping with while always results in missing value where TRUE/FALSE is expectedR - 使用 while 循环总是会导致预期为 TRUE/FALSE 的缺失值
【发布时间】:2021-05-13 08:48:01
【问题描述】:

编辑:到目前为止,我实现了提供的解决方案,现在代码看起来更干净了。这是最终找到我的错误的关键。这是我没有在 while 循环中检查的逻辑条件。迭代器可能会超过向量中的元素数量,从而将“NA”传递给 while 条件!谢谢

我还更改了解决方案,使用向量赋值来存储结果,然后在 for 循环之后重新组合,因为向量索引似乎比循环内的 data.table 索引和值赋值要快得多。


请让我首先为任何错误和缺乏解决我的问题的信息道歉,因为这是我迄今为止的第一篇文章。我已经读过,每当计算中出现错误并且条件的值导致错误时,这可能会意外发生,例如 if (TRUE & sqrt(-1))

已经好几天了,我仍然收到此错误。这真的让我很头疼,因为这些代码背后的内在逻辑实际上非常简单,我仍然无法正确地将其形式化。它如下所示:对于包含在大小为 N 的向量中的每个唯一债券 ID(使用 i 循环),其对应到期日的静态值与不同规则集的 7 个周期的结束日期(使用 k 循环)比较确定各个问题属于哪些具有独特规则的时段,然后通过循环遍历所有时段的大小阈值(按 l 循环)来确定特定问题是否违反了这些最小大小要求。如果确定违规,我可以指定违规日期。如果(l == k),我可以认为在问题成熟度所在的所有时期,也成功地循环通过了相应的大小要求检查,因此没有违反任何规则。然后,我将条件检查的结果分配为新 data.table 列中的相应二进制值以及违规日期。到目前为止,我真的无法确定是什么导致了这个错误。

我的数据如下所示。我有一个非常大的 data.table,其中包含债券发行标识符和描述这些问题的各种其他列变量。它最初是使用read_dta() 函数导入的,然后转换为带有setDT() 的data.table。

我从这个 data.table 中提取 3 列,使用

issue_IDs.vec     <- as.numeric(issues.dt[[2]])
maturity.vec      <- as.Date(issues.dt[[8]], "%Y-%m-%d")
offerings_atm.vec <- as.numeric(issues.dt[[33]])

接下来,我将索引的资格标准转换为如下。

# (1) Creating size requirement end periods (valid thru) ----
size_req_per_1 <- as.Date("1992-01-01", "%Y-%m-%d")
size_req_per_2 <- as.Date("1994-01-01", "%Y-%m-%d")
size_req_per_3 <- as.Date("1999-07-01", "%Y-%m-%d")
size_req_per_4 <- as.Date("2003-10-01", "%Y-%m-%d")
size_req_per_5 <- as.Date("2004-07-01", "%Y-%m-%d")
size_req_per_6 <- as.Date("2017-02-01", "%Y-%m-%d")
size_req_per_7 <- as.Date("2021-02-01", "%Y-%m-%d")
size_req_val_per.vec <- c(size_req_per_1, size_req_per_2, size_req_per_3, size_req_per_4,
                          size_req_per_5, size_req_per_6, size_req_per_7)

# (2) Create a size requirement threshold per rules' validity period ----
size_req_thresh_1   <-  25000
size_req_thresh_2   <-  50000
size_req_thresh_3   <- 100000
size_req_thresh_4   <- 150000
size_req_thresh_5   <- 200000
size_req_thresh_6   <- 250000
size_req_thresh_7   <- 300000
size_req_thresh.vec <- c(size_req_thresh_1, size_req_thresh_2, size_req_thresh_3,
                         size_req_thresh_4, size_req_thresh_5, size_req_thresh_6,
                         size_req_thresh_7)

接下来,我确实编写了一个循环来执行条件检查,以查找存储在 issues_ID.vec 中的每个问题 ID,如果它们在到期期间违反了最小发行大小的索引资格标准。我通过将迭代器变量 i 的值作为位置值传递给 issues_ID.vec 来做到这一点。

# (3) Looping through a set of conditional check to find out if and if so when a particular issue violated the size requirement ---
   
# Iterator variables ----
# Length of issues.dt
j <- issues.dt[, .N]

# Main iterator looping through all entries of isssues.dt extracted as vector
i <- 1

# Looping through vector elements of issue rules (vec. 1: validity periods)
k <- 1

# Looping through vector elements of issue rules (vec. 2: size thresholds) 
l <- 1



# Loop

for (i in 1:j) {
  id            <- issue_IDs.vec[i]
  maturity      <- maturity.vec[i]
  offering_atm  <- issue_IDs.vec[i]
  
  k <- 1
  maturity_comp <- size_req_val_per.vec[k]
  
  while (maturity >= maturity_comp) {
    if (k < 7) {
      k <- k + 1
      maturity_comp <- size_req_val_per.vec[k]
    } else {
      break
    }
  }
  
  l <- 1
  offering_size_comp <- size_req_thresh.vec[l]
  
  for (l in 1:k) {
    if (offering_atm >= offering_size_comp) {
      offering_size_comp <- size_req_thresh.vec[l]
      next
    } else {}
  }
  
  if (l == k) {
    issues.dt[ISSUE_ID == id,
              `:=`(SIZE_REQ_VIOLATION = 0,
                   SIZE_REQ_VIOLATION_DATE = NA)]
  } else {
    issues.dt[ISSUE_ID == id,
              `:=`(SIZE_REQ_VIOLATION = 1,
                   SIZE_REQ_VIOLATION_DATE = size_req_val_per.vec[l])]
  }
  i <- i + 1
}

每当我尝试以简化版本运行代码时,例如

k <- 1
for (1 in 1:7) {
  print(maturity >= maturity_comp)
  k <- k + 1
  maturity_comp <- format(as.Date(size_req_val_per.vec[k]), "%Y-%m-%d")
}

代码运行平稳,并且总是导致打印的评估结果为 TRUE 或 FALSE,这取决于我最初创建特定债券发行的相应静态期限的 ID。在这个阶段,我已经用尽了我的故障排除技巧。

感谢你们的任何意见,如果您需要任何其他信息、解释等,请告诉我。

【问题讨论】:

  • for (l in 1:k) 循环中包含l &lt;- l + 1 对我来说很奇怪。 for() 表示 l 将迭代为 1, 2, 3, 4, ... k。如果要跳转到下一个迭代,请使用next
  • i主循环中,您是否故意使用k定义maturity_comp &lt;- format(as.Date(size_req_val_per.vec[k]), "%Y-%m-%d") 之前重置k &lt;- 1?这似乎是个问题。
  • 回答您的第一条评论。你是绝对正确的!我将变量赋值后的行中的l &lt;- l + 1 替换为next
  • 关于您的第二条评论:当我在主 for 循环之外定义 k &lt;- 1 时,我可以使用 k 来确定相应的成熟度。我在循环结束时reset k to 1,因此债券的静态到期日期的比较开始于存储在size_req_val_per.vec中的第一个日期,每i^次迭代的 for 循环。这是正确的方法吗?我需要这是一个单独的迭代器变量,因为 i 上升到提取向量的总长度,而不是 k ,它应该只从 1 到 7(7 个周期)每次 i^th 迭代。
  • 好吧,你设置了k &lt;- 1 before 循环,所以它在第一次i 迭代之前运行。在循环结束时,我没有看到任何k &lt;- 1 的重置。这意味着当您进行i = 2 迭代时,k 在定义maturity_comp 时仍然具有来自i = 1 迭代的最终值,然后然后您重置k &lt;-1。似乎循环内的 k &lt;- 1 应该在此之前,除非您希望从上一次迭代中“记住”maturity_comp

标签: r loops data.table


【解决方案1】:

我认为答案在于 Gregor 的评论。您格式化日期的方式会将它们转换为字符变量。这是一个简单的例子:

Exmpl<-as.Date("08-25-2020", "%m-%d-%Y")
class(Exmpl)

[1] "Date"

##Not your preferred format, but it is a Date variable##
Exmpl
"2020-08-25"

##Formatting changes it to a character
Exmpl2<-format(as.Date(Exmpl), "%m-%d-%Y")
class(Exmpl2)
[1] "character"

当您在while() 函数中调用它们时,R 会尝试进行比较以确定条件(即成熟度大于或等于成熟度补偿)是 TRUE 还是 FALSE(逻辑变量)。因为你有字符变量,R 不能进行这种比较。

我认为如果您不格式化日期,您的代码将可以工作,而只需将它们读入并将它们保留为 YYYY-mm-dd 格式。

【讨论】:

  • 感谢您的评论。我看到这导致了一个问题,实际上没有转换的原因。我编辑了我的原始代码,现在将日期列maturity 直接提取为日期并删除format(..., "%Y-%m-%d")Date 类型的所有其他数据在赋值时定义为 f.ex。 size_req_val_per.vec。不过,我仍然会收到此错误
  • 注意:就我而言,我做了 3 次条件检查。 (1) while (maturity &gt;= maturity_comp) 两个对象都是 Date 类型 (2) if (offering_atm &gt;= offering_size_comp) 两个对象都是 Numeric (3) if (l == k) 两个变量(迭代器)都是 Numeric 类型 2 + 3 都不会导致任何问题,但是代码已经在 while 循环中的条件检查 1 处中断。
  • 您可能需要开始运行打印语句到循环中断的地方。我会在 while() 函数之前添加 print(class(maturity)print(class(maturity_comp)) 并重新运行循环。如果你这样做,请在此处发布输出
  • 我稍后会做。我也开始怀疑这里的东西了!注释掉 while 循环后,代码不会中断,即使语义没有任何意义。
  • 结果为@​​987654333@
猜你喜欢
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
相关资源
最近更新 更多