【问题标题】:Replacing dates in column with a for loop用 for 循环替换列中的日期
【发布时间】:2021-02-03 04:58:19
【问题描述】:

我正在帮助某人尝试获得他们想要的解决方案,而无需对他们提出的代码进行太多更改。我知道 for 循环不是必需的。例如,您可以通过将datenumeric <- as.Date(datenumeric, "%Y%m%d") 添加到他们的convertdatereadable 函数中,然后将其传递给lapply 来解决它。我无法使用 for 循环复制相同的结果。

请求

dat 有一个 date 列,其中包含以下 double 值:

1947.01
1947.02
1947.03
1947.04
1947.05

请求是将date列转换为日期格式format = "%Y%m%d"

可重现的示例

dat <- structure(list(date = c(1947.01000976562, 1947.02001953125, 1947.03002929688, 
1947.0400390625, 1947.05004882812), sp500 = c(15.210000038147, 
15.8000001907349, 15.1599998474121, 14.6000003814697, 14.3400001525879
), divyld = c(4.48999977111816, 4.38000011444092, 4.6100001335144, 
4.75, 5.05000019073486), i3 = c(0.379999995231628, 0.379999995231628, 
0.379999995231628, 0.379999995231628, 0.379999995231628), ip = c(22.3999996185303, 
22.5, 22.6000003814697, 22.5, 22.6000003814697), pcsp = c(NA, 
46.5483322143555, -48.6076202392578, -44.3271369934082, -21.3698806762695
), rsp500 = c(NA, 50.9283332824707, -43.9976196289062, -39.5771369934082, 
-16.319881439209), pcip = c(NA, 5.35716342926025, 5.33335399627686, 
-5.30975437164307, 5.33335399627686), ci3 = c(NA, 0, 0, 0, 0), 
    ci3_1 = c(NA, NA, 0, 0, 0), ci3_2 = c(NA, NA, NA, 0, 0), 
    pcip_1 = c(NA, NA, 5.35716342926025, 5.33335399627686, -5.30975437164307
    ), pcip_2 = c(NA, NA, NA, 5.35716342926025, 5.33335399627686
    ), pcip_3 = c(NA, NA, NA, NA, 5.35716342926025), pcsp_1 = c(NA, 
    NA, 46.5483322143555, -48.6076202392578, -44.3271369934082
    ), pcsp_2 = c(NA, NA, NA, 46.5483322143555, -48.6076202392578
    ), pcsp_3 = c(NA, NA, NA, NA, 46.5483322143555), month = c(-156, 
    -155, -154, -153, -152)), row.names = c(NA, 5L), class = "data.frame")

包含转换日期可读函数的代码

convertdatereadable <- function(datenumeric){
    datenumeric <- trunc(datenumeric * 10000 + 1)
    datenumeric <- as.character(datenumeric)
    return(datenumeric)
}

dat[1] <- lapply(dat[1], convertdatereadable)


for (n in 1:nrow(dat)){
 dat$date <- as.Date(dat[n, 1], format = "%Y%m%d")
}

当前状态下的 for 循环输出正确的格式,但不幸的是,它复制了所有 5 行的第一个日期。

电流输出不正确


dat[1]

#>         date
#> 1 1947-01-01
#> 2 1947-01-01
#> 3 1947-01-01
#> 4 1947-01-01
#> 5 1947-01-01

在保持 for 循环的同时获得所需的输出


dat[1]

#>         date
#> 1 1947-01-01
#> 2 1947-02-01
#> 3 1947-03-01
#> 4 1947-04-01
#> 5 1947-05-01

我认为这会起作用,但它没有:

for (n in 1:nrow(dat)){
 dat[n, 1] <- as.Date(dat[n, 1], format = "%Y%m%d")
}

【问题讨论】:

  • dat$date[n] &lt;- ... - 您也需要在作业的左侧进行索引。由于您只是依次替换每个元素,因此 dat$dateclass 永远不会更改为 Date - 之后您将不得不在循环之外强制这种情况,例如 class(dat$date) &lt;- "Date"
  • “我正在帮助某人尝试获得他们想要的解决方案,而无需对他们提出的代码进行太多更改” - 可以说您可以通过向他们展示您的矢量化解决方案来帮助他们更多:)
  • @thelatemail - 在实现class(dat$date) &lt;- "Date" 后尝试打印dat 时,遇到以下错误:character string is not in a standard unambiguous format。如果您不介意发布解决此错误的解决方案,我愿意接受。非常感谢。
  • @iamericfletcher - 完成

标签: r date for-loop


【解决方案1】:

正如其他人所说,使用as.Date(..., format="%Y%m%d") 是执行此操作而不是循环的方法。

但要了解这里发生了什么,请将其分解并检查每行之后的输出状态:

首先,让我们修复循环以通过n 索引两边,以便依次覆盖每个值:

for (n in 1:nrow(dat)){
 dat$date[n] <- as.Date(dat$date[n], format = "%Y%m%d")
}

这会导致自 1970 年 1 月 1 日以来的天数的字符表示(日期作为 numeric 版本存储在 R 中):

dat$date
#[1] "-8401" "-8370" "-8342" "-8311" "-8281"
class(dat$date)
#[1] "character"

为什么是字符而不是数字?因为您使用的是]&lt;- 而不是&lt;-,也就是说,您不会覆盖整个dat$date 列,而是覆盖每个dat$date[1]dat$date[2] 等。这将在这种情况下保留源class,因为数字数据始终可以强制转换为字符,但字符数据不一定强制转换为数字。例如:

x <- c("a","b","c")
x[1] <- 1
x
#[1] "1" "b" "c"
 
 
x <- c(1,2,3)
x[1] <- "a"
x
#[1] "a" "2" "3"

如果你覆盖整个对象,类将会改变:

x <- c("a","b","c")
x <- c(1,2,3)
x
#[1] 1 2 3

然后你需要强制类回到最新状态:

class(dat$date) <- "Date"
dat$date
#[1] "1947-01-01" "1947-02-01" "1947-03-01" "1947-04-01" "1947-05-01"
class(dat$date)
#[1] "Date"

你也可以通过显式转换得到同样的结果:

dat$date <- as.Date(as.numeric(dat$date), origin="1970-01-01")

【讨论】:

    【解决方案2】:

    你快完成了。 您只需更改循环中的变量,如下所示:

    for (n in 1:nrow(dat)){
     dat$crcteddate <- as.Date(dat$date, format = "%Y%m%d")
    }
    

    这将创建一个名为“crcteddate”的列并提供以下输出:

    "1947-01-01" "1947-02-01" "1947-03-01" "1947-04-01" "1947-05-01"
    

    您错误地调用了日期列 dat[n,1] 而不是直接调用 dat$date。

    【讨论】:

      猜你喜欢
      • 2021-10-02
      • 1970-01-01
      • 2019-04-04
      • 2018-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多