【问题标题】:Passing Sequence of Dates to dataframe column将日期序列传递给数据框列
【发布时间】:2021-09-10 08:19:52
【问题描述】:

我正在尝试将一系列日期传递给数据框:

DF_1 <- as.data.frame(matrix(ncol=2))            
days <-seq(as.Date("2016-01-01"), as.Date(Sys.time(),"%Y-%m-%d"), by="days")
    
for (i in 1:length(days)) {
      print(days[i])
      DF_1[i,1] <- days[i]
    }

打印函数的结果是:

[1] "2021-06-23"
[1] "2021-06-24"
[1] "2021-06-25"
[1] "2021-06-26"
[1] "2021-06-27"
[1] "2021-06-28

" 但是 DF1 中的第 1 列是:

16801
16802
16803
16804
16805

为什么数据帧中日期的顺序会发生变化?

【问题讨论】:

  • 您应该避免for 循环。最好将数据传递给 data.frame 构造函数:DF_1 &lt;- data.frame(days = seq(as.Date("2016-01-01"), as.Date(Sys.time(),"%Y-%m-%d"), by="days"))。否则,您必须担心部分更改列数据类型。
  • 这篇帖子stackoverflow.com/questions/6434663/… 应该会告诉您发生这种情况的原因以及可能的解决方案。

标签: r dataframe date


【解决方案1】:

您也可以使用dplyr 将日期添加到您的初始化数据框中。

library(dplyr)

# Set up your dataframe based on the length of days.
days <-seq(as.Date("2016-01-01"), as.Date(Sys.time(),"%Y-%m-%d"), by="days")
DF_1 <- as.data.frame(matrix(ncol=2, nrow = length(days)))

# Then, add the date data to the first column in the initialized dataframe.
DF_2 <- DF_1 %>%
  dplyr::mutate(V1 = days)

另一种选择是使用purrr 将日期数据转换为小标题。如果需要,您可以重命名该列并创建第二个列。

library(purrr)
library(dplyr)

df <- days %>% 
  purrr::map_df(as_tibble) %>% 
  dplyr::rename(date = 1) %>% 
  dplyr::mutate(V2 = NA)

【讨论】:

    【解决方案2】:

    最好将'DF'初始化为

    DF_1 <- data.frame(days)
    str(DF_1)
    'data.frame':   2006 obs. of  1 variable:
     $ days: Date, format: "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" ...
    

    或者,如果我们仍想使用for 循环,请使用Date 类而不是logical 进行初始化(matrix 创建NA 行,这是合乎逻辑的)

    DF_1 <- data.frame(col1 = as.Date(rep(NA, length(days))))
    

    现在,如果我们进行循环

    for (i in 1:length(days)) {
          print(days[i])
          DF_1[i,1] <- days[i]
        }
    

    查看班级

    str(DF_1)
    'data.frame':   2006 obs. of  1 variable:
     $ col1: Date, format: "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" ...
    

    问题是Date 强制转换为其整数存储值。我们也可以在unlist 时找到该行为

    unlist(as.list(head(days)))
    [1] 16801 16802 16803 16804 16805 16806
    

    unclass

    unclass(head(days))
    [1] 16801 16802 16803 16804 16805 16806
    

    如果输入是list,则可以使用do.call 中的c 进行更正

    do.call(c, as.list(head(days)))
    [1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06"
    

    或者之后通过在as.Date 中指定origin 将整数转换回Date

    as.Date(unlist(as.list(head(days))), origin = '1970-01-01')
    [1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06"
    

    【讨论】:

    • 谢谢它的工作。但是为什么会这样呢?无论如何,用 for 传递都不行?
    • @Mantanamm 在将 data.frame 列初始化为Date 类后,您是否尝试过我使用for 循环发布的第二个解决方案
    • @Mantanamm Date 存储模式为 integer 并且发生类型切换,因为您的初始数据是合乎逻辑的。此外,输入数据只是单行,会被追加
    • 感谢您的解释。我试图理解这个概念,而不是解决问题。
    • @Mantanamm 我知道您的问题可能是如何从已经运行的大循环中连接日期。使用Dates,由于是整数存储方式,处理起来要更加小心
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 2017-09-23
    相关资源
    最近更新 更多