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

R-如何格式化数据表/数据框中几列的日期

  •  0
  • Daniel  · 技术社区  · 9 年前

    我想在中设置几个列的格式 datatable/dataframe lubridate column indexing

    假设有一个 其中有几个未格式化的 date 润滑 .

    library(data.table)
    library (lubridate) 
    
    > dt <- data.frame(date1 = c("14.01.2009", "9/2/2005",  "24/1/2010", "28.01.2014"),var1 = rnorm(4,2,1), date2 = c("09.01.2009", "23/8/2005","17.01.2000", "04.01.2005"))
    > dt
           date1     var1      date2
    1 14.01.2009 2.919293 09.01.2009
    2   9/2/2005 2.390123  23/8/2005
    3  24/1/2010 0.878209 17.01.2000
    4 28.01.2014 2.224461 04.01.2005
    
    dt <- setDT(dt)
    

    > dmy(dt$date1,dt$date2)# his dose not generate two columns
    [1] "2009-01-14" "2005-02-09" "2010-01-24" "2014-01-28" "2009-01-09" "2005-08-23"
    [7] "2000-01-17" "2005-01-04"
    
    > as.data.frame(dmy(dt$date1,dt$date2)) 
      dmy(dt$date1, dt$date2) # this dose not generate two columns either  
    1              2009-01-14
    2              2005-02-09
    3              2010-01-24
    4              2014-01-28
    5              2009-01-09
    6              2005-08-23
    7              2000-01-17
    8              2005-01-04
    
    
    dmy(dt[,.SD, .SD =c(1,3)])
    [1] NA NA
    
    > sapply(dmy(dt$date1,dt$date2),dmy)
    [1] NA NA NA NA NA NA NA NA
    Warning messages:
    1: All formats failed to parse. No formats found. 
    

    非常感谢您的帮助。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Luís Telles    9 年前

    怎么样:

    dt <- data.frame(date1 = c("14.01.2009", "9/2/2005",  "24/1/2010", "28.01.2014"),var1 = rnorm(4,2,1), date2 = c("09.01.2009", "23/8/2005","17.01.2000", "04.01.2005"))
    
    for(i in c(1,3)){
         dt[,i] <- dmy(dt[,i])
    }
    
        2
  •  1
  •   juan    9 年前

    这是一个 data.table k 名为的列 dateX :

    k = 2
    date_cols = paste0('date', 1:k)
    for (col in date_cols) {
        set(dt, j=col, value=dmy(dt[[col]])
    }
    

    你可以避免循环,但显然循环可能更快;看见 this answer

    dt[,(date_cols) := lapply(.SD, dmy), .SDcols=date_cols]
    

    如果您有aribitray列名,则假设数据看起来与OP中的一样

    date_cols = names(dt)[grep("^\\d{4}(\\.|/)", names(dt))]
    date_cols = c(date_cols, names(dt)[grep("(\\.|/)\\d{4}", names(dt))])
    

    . / ,您可以将其合并为一个 grep

        3
  •  1
  •   Val Srinivas    9 年前

    这远不是完美的解决方案,应该更一般:

    这里唯一的假设是,日期列包含由以下任一项分隔的数字: . , / - .如果有其他分隔符,可以添加。但是,如果你有另一个类似的变量,但没有日期,这将不会很好地工作。

    for (j in seq_along(dt)) if (all(grepl('\\d+(\\.|/|-)\\d+(\\.|/|-)\\d+',dt[,j]))) dt[,j] <- dmy(dt[,j])

    这将遍历列并检查是否可以使用正则表达式显示日期。如果是这样,它会将其转换为日期并覆盖该列。

    使用 data.table

    for (j in seg_along(dt)) if (all(grepl('\\d+(\\.|/|-)\\d+(\\.|/|-)\\d+',dt[,j]))) set(dt,j = j, value = dmy(dt[[j]]))

    all 具有 any 如果该列中有任何匹配项,则可以假设该列中的所有值都是可以读取的日期 dmy