我有一个数据框架,其中包含分散在列中的不同格式的日期,我希望将它们标准化为单一格式。我可以对异构日期的单个向量进行标准化,如在d
中,通过在向量(如formats
(中定义可能的日期格式并将其传递给as.Date
:
d <- c("01-02-2009","01/04/2009","15-Jan-2019", "12-12-2020")
formats <- c("%d-%m-%Y", "%d/%m/%Y", "%d-%b-%Y")
format(as.Date(d, format = formats), "%d-%b-%Y")
[1] "01-Feb-2009" "01-Apr-2009" "15-Jan-2019" "12-Dez-2020"
但这对数据帧不起作用:
df <- data.frame(Transaction = c("01-Mar-2015", "31-01-2012", "15/01/1999"),
Delivery = c("01-02-2018", "01/08/2016", "17-09-2007"),
Return = c("27/11/2009", "22-Jan-2013", "20-Nov-1987"))
在这里,标准化只是部分起作用:
df[,1:3] <- lapply(df[,1:3], function(x) format(as.Date(x, format = formats), "%d-%b-%Y"))
df
Transaction Delivery Return
1 <NA> 01-Feb-2018 <NA>
2 <NA> 01-Aug-2016 <NA>
3 <NA> <NA> 20-Nov-1987
如何在整个数据帧中将日期标准化为%d-%b-%Y
格式?
使用mutate_all
,您可以使用lubridate
中的parse_date_time
函数将数据帧的所有字符列转换为单一日期格式,并在orders
参数中传递格式列表。
然后,您可以使用format
:将这些日期格式化为所需的输出
library(lubridate)
library(dplyr)
formats <- c("%d-%m-%Y", "%d/%m/%Y", "%d-%b-%Y")
df %>% mutate_all( ~parse_date_time(., orders = formats)) %>%
mutate_all(~format(., "%d-%b-%Y"))
Transaction Delivery Return
1 01-Mar-2015 01-Feb-2018 27-Nov-2009
2 31-Jan-2012 01-Aug-2016 22-Jan-2013
3 15-Jan-1999 17-Sep-2007 20-Nov-1987
使用apply
可以执行:
library(lubridate)
apply(df, 2, function(x) format(parse_date_time(x, orders = formats), "%d-%b-%Y"))
Transaction Delivery Return
[1,] "01-Mar-2015" "01-Feb-2018" "27-Nov-2009"
[2,] "31-Jan-2012" "01-Aug-2016" "22-Jan-2013"
[3,] "15-Jan-1999" "17-Sep-2007" "20-Nov-1987"
它能回答你的问题吗?
注意:parse_date_time
正在为lubridate version 1.7.8
工作。对于lubridate version 1.7.4
,可以使用parse_date
并用format
替换orders
问题是列中的formats
与已经创建的不同。所以,我们需要像这样的东西
as.Date(df$Transaction, format = c("%d-%b-%Y", "%d-%m-%Y", "%d/%m/%Y"))
#[1] "2015-03-01" "2012-01-31" "1999-01-15"
即OP指定的CCD_ 18是
formats
#[1] "%d-%m-%Y" "%d/%m/%Y" "%d-%b-%Y"
如果我们检查"交易"列
df$Transaction
#[1] 01-Mar-2015 31-01-2012 15/01/1999
它包括现有格式中没有的%d-%m-%Y
和%d/%m/%Y
此外,为了更清楚,传递的矢量format
正在对format
进行元素比较
as.Date(df$Transaction, format = c("%d-%b-%Y", "%d/%m/%Y"))
#[1] "2015-03-01" NA NA
即,通过传递"%d/%m/%Y"
,它应该与第三个条目匹配,但因为它是元素比较,所以它与第二个元素进行检查,然后对向量格式进行循环,因为它的长度小于"事务"列的长度
这意味着,如果我们的数据集是1e6行,那么它期望1e6格式应该与每个元素匹配。
或使用anytime
中的anydate
library(anytime)
addFormats(c('%d-%m-%Y', '%d/%m/%Y'))
df[] <- lapply(df, function(x) format(anydate(x), "%d-%b-%Y"))
df
# Transaction Delivery Return
#1 01-Mar-2015 01-Feb-2018 27-Nov-2009
#2 31-Jan-2012 01-Aug-2016 22-Jan-2013
#3 15-Jan-1999 17-Sep-2007 20-Nov-1987