代码之家  ›  专栏  ›  技术社区  ›  Rookatu

如何在日期不转换类型的情况下将列表转换为数据帧

  •  3
  • Rookatu  · 技术社区  · 6 年前

    我正在尝试编写一个脚本,它可以获取一个文件,查找与该文件相关的一些元数据,并基于该元数据转换某些列。例如,假设我的数据看起来像以下输出:

    test_data <- data.frame(date1 = c("03/02/2018","04/25/2018"),date2 = c("9/14/17","9/27/17"))
    

    假设基于元数据查找,我发现 date1 date2 输入文件的

    date_formats <- c("%m/%d/%Y","%m/%d/%y")
    

    所以我的脚本将继续定义 index 作为包含值的布尔向量 TRUE 我有一个日期栏 FALSE 否则,然后尝试将所有此类列转换为标准的R日期格式:

    test_data[,index] <- as.data.frame( 
                         lapply(test_data[,index],as.Date,
                         format = date_formats[index],
                                   origin ="1970-01-01")))
    

    但这会产生一些奇怪的结果:

      date1      date2
    1 2018-03-02 0017-09-14
    2 2020-04-25 2017-09-27
    

    请注意,(1,2)和(2,1)项的年份已关闭。我不明白为什么其他值被正确转换。这是个谜。

    另一个谜团是,如果我试图只转换一个列,比如

    as.data.frame(lapply(test_data[,1],as.Date,format = c("%m/%d/%Y")))
    

    然后我得到不想要的结果:

    structure.17592..class....Date.. structure.17646..class....Date..
    1                       2018-03-02                       2018-04-25
    

    如果我先用 cbind 洛杉矶

    as.data.frame( cbind(lapply(test_data[,1],as.Date,format = c("%m/%d/%Y"))))
    

    那么我得到的是原始的、未格式化的日期值,因为 小精灵 :

        V1
    1 17592
    2 17646
    

    那么,我如何编写这种通用方法,它可以处理任意数量的具有不同格式的列,并将它们转换为数据帧中相同格式的日期类型?

    2 回复  |  直到 6 年前
        1
  •  4
  •   moodymudskipper    6 年前

    试试这个:

    test_data <- data.frame(date1 = c("03/02/2018","04/25/2018"),date2 = c("9/14/17","9/27/17"))
    date_formats <- c("%m/%d/%Y","%m/%d/%y")
    index <- c(TRUE,TRUE)
    
    test_data[,index] <- 
      as.data.frame( 
        lapply(which(index),function(i) 
          as.Date(test_data[[i]],
                  format = date_formats[i],
                  origin ="1970-01-01")))
    
    #        date1      date2
    # 1 2018-03-02 2017-09-14
    # 2 2018-04-25 2017-09-27
    

    这个 index 你在喂 date_formats 在你的衣领环总是长度2,衣领没有环它。我们需要将布尔索引转换为数值,然后在其上循环。

    下面是实现您所需的更清晰的代码:

    test_data[,index] <- 
      Map(as.Date,test_data[index],date_formats[index],origin ="1970-01-01")
    #        date1      date2
    # 1 2018-03-02 2017-09-14
    # 2 2018-04-25 2017-09-27
    
        2
  •  1
  •   MKR    6 年前

    op的意图似乎是从文件中读取数据,其中的某些列包含不同格式的日期。 @Moody_Mudskipper 已经提供了一个很好的解决方案,可以在从文件中读取数据后对其进行转换。

    另一种选择是 colClasses read函数的参数(即 read.table , read.csv 等)本身并转换日期列。

    # Test data to be read from file. I have added one more column ID in data from OP
    textData <- "
    ID       date1   date2
    1 03/02/2018 9/14/17
    2 04/25/2018 9/27/17"
    
    setClass("dateformat1")
    setClass("dateformat2")
    
    setAs("character", "dateformat1", function(from)as.Date(from, format = "%m/%d/%Y"))
    setAs("character", "dateformat2", function(from)as.Date(from, format = "%m/%d/%y"))
    
    
    read.table(text = textData, header = TRUE, stringsAsFactors = FALSE, 
               colClasses = c("numeric", "dateformat1","dateformat2"))
    
    #   ID      date1      date2
    # 1  1 2018-03-02 2017-09-14
    # 2  2 2018-04-25 2017-09-27