R - 如何格式化 datatable/dataframe 中多列的日期
R - How to format the date of several columns in a datatable/dataframe
我想使用 lubridate
和 column indexing
格式化 datatable/dataframe
中的多个列。
假设有一个非常大的数据集,其中有几个未格式化的date
列。问题是我如何识别这些列(最有可能通过索引),然后使用 lubridate
.
在一个脚本中同时格式化它们
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.
非常感谢任何帮助。
怎么样:
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])
}
这里有一个 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]
编辑
如果你有任意列名,假设数据看起来像 OP
date_cols = names(dt)[grep("^\d{4}(\.|/)", names(dt))]
date_cols = c(date_cols, names(dt)[grep("(\.|/)\d{4}", names(dt))])
如果分隔符的数量多于 .
或 /
,您可以添加正则表达式,并且您可以将其组合成一个 grep
,但这对我来说更清楚。
远非完美,这是一个应该更通用的解决方案:
此处唯一的假设是,日期列包含由 .
、/
或 -
分隔的数字。如果有其他分隔符,可以添加它们。但是如果你有另一个类似的变量,但不是日期,这将无法正常工作。
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
.
我想使用 lubridate
和 column indexing
格式化 datatable/dataframe
中的多个列。
假设有一个非常大的数据集,其中有几个未格式化的date
列。问题是我如何识别这些列(最有可能通过索引),然后使用 lubridate
.
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.
非常感谢任何帮助。
怎么样:
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])
}
这里有一个 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]
编辑
如果你有任意列名,假设数据看起来像 OP
date_cols = names(dt)[grep("^\d{4}(\.|/)", names(dt))]
date_cols = c(date_cols, names(dt)[grep("(\.|/)\d{4}", names(dt))])
如果分隔符的数量多于 .
或 /
,您可以添加正则表达式,并且您可以将其组合成一个 grep
,但这对我来说更清楚。
远非完美,这是一个应该更通用的解决方案:
此处唯一的假设是,日期列包含由 .
、/
或 -
分隔的数字。如果有其他分隔符,可以添加它们。但是如果你有另一个类似的变量,但不是日期,这将无法正常工作。
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
.