【问题标题】:Is there a way to check if a column is a Date in R?有没有办法检查列是否是 R 中的日期?
【发布时间】:2013-08-13 06:15:08
【问题描述】:

这是对这个问题的伪跟进:Why is ggplot graphing null percentage data points?

假设这是我的数据集:

Date        AE      AA      AEF     Percent
1/1/2012    1211    1000    3556    0.03
1/2/2012    100     2000    3221    0.43
1/3/2012    3423    10000   2343    0.54
1/4/2012    10000   3000    332     0.43
1/5/2012    2342    500     4435    0.43
1/6/2012    2342    800     2342    0.23
1/7/2012    2342    1500    1231    0.12
1/8/2012    111     2300    333 
1/9/2012    1231    1313    3433    
1/10/2012   3453    5654    222 
1/11/2012   3453    3453    454 
1/12/2012   5654    7685    3452 

> str(data)
'data.frame':   12 obs. of  5 variables:
 $ Date   : Factor w/ 12 levels "10/11/2012","10/12/2012",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ AE     : int  1211 100 3423 10000 2342 2342 2342 111 1231 3453 ...
 $ AA     : int  1000 2000 10000 3000 500 800 1500 2300 1313 5654 ...
 $ AEF    : int  3556 3221 2343 332 4435 2342 1231 333 3433 222 ...
 $ Percent: num  0.03 0.43 0.54 0.43 0.43 0.23 0.12 NA NA NA ...

我需要一些东西来说明“日期”列是日期类型,而不是数字或字符类型(这是因为我必须将数据输入的“日期”列转换为带有 as 的实际日期。 Date(),假设我不知道数据集的列名)。

is.numeric(data[[1]]) returns False
is.character(data[[1]]) returns False

我在 Excel 中创建了“日期”列,将列格式化为“日期”格式,然后将文件另存为 csv。这是R中的什么类型?我寻求类似于上述返回 TRUE 的表达式。

【问题讨论】:

  • 执行str(data_set) 并将其添加到您的问题中。
  • inherits(data[[1]], "Date")
  • 谢谢 Excel,嗯?当您在 csv 中阅读时,请务必执行 stringsAsFactors = FALSE 但这并不能完全解决您的问题,它会将其作为字符读取,您仍然需要进行转换。如果你要经常使用日期,我推荐lubridate 包。
  • 啊,哎呀,你可能不知道哪一栏是日期?它会是唯一的性格吗?这可能是诀窍。
  • stringsAsFactorsread.csv 的一个参数,它决定了字符串的处理方式:因子与字符。所以你说你需要读取一个 csv 但日期可以是任何列并且它可以被称为任何东西? names(data_set) 有帮助吗?

标签: r


【解决方案1】:

使用inherits 检测参数是否具有数据类型Date

is.date <- function(x) inherits(x, 'Date')

sapply(list(as.Date('2000-01-01'), 123, 'ABC'), is.date)
#[1]  TRUE FALSE FALSE

如果您想检查字符参数是否可以转换为Date,请使用:

is.convertible.to.date <- function(x) !is.na(as.Date(as.character(x), tz = 'UTC', format = '%Y-%m-%d'))

sapply(list('2000-01-01', 123, 'ABC'), is.convertible.to.date)
# [1]  TRUE FALSE FALSE

【讨论】:

  • 这假设您已经弄清楚哪些列已经是日期,并正确转换它们。它为我的测试数据集的所有 3 列返回 FALSE
  • 您还缺少 POSIXct 类,这是 R 中的有效日期类,没有额外的 Date 类。
【解决方案2】:

您可以尝试将所有列强制转换为 as.Date 并查看哪些列成功。您需要指定您希望日期采用的格式。例如:

data <- data.frame(
  Date=c("10/11/2012","10/12/2012"),
  AE=c(1211,100),
  Percent=c(0.03,0.43)
)

sapply(data, function(x) !all(is.na(as.Date(as.character(x),format="%d/%m/%Y"))))
#Date      AE Percent 
#TRUE   FALSE   FALSE 

【讨论】:

  • 这是我遇到的最准确的事情。你能解释一下你是怎么做到的吗?我似乎找不到关于 '!all' 和 is.na 的任何信息。
  • 关于is.naall,试试看这个:?is.na; x &lt;- c(1,2,3,NA,5); is.na(x); ?all; y &lt;- c(1,2,3,4,5); all(y &gt; 0); !all(y &gt; 0); !all(y &gt; 3);
  • @erosennin - 您是否将 format= 参数与您的日期格式相匹配?
  • 不,我有这么多列,但我现在看到您指定我们必须知道格式。太糟糕了。
  • 这不是在回答问题。 OP 说'我需要一些东西来告诉'日期'列是日期类型'。所以需要一个简单但可靠的检查,不是转换来查看它是否有效,因为我们可以假设该列已经是 Date 类型。但是我们如何测试呢?请向下滚动。
【解决方案3】:

我知道这个问题很老了,但我确实想提一下,lubridate 包中现在有一个函数,用于 is.Dateis.POSIXt

sapply(list(as.Date('2000-01-01'), 123, 'ABC'), is.Date)
[1]  TRUE FALSE FALSE

【讨论】:

  • 不应该 NA 返回 NA 而不是 FALSE?其他测试将 NA 保留为 NA...sapply(list(as.Date('2000-01-01'), 123, 'ABC', NA), is.Date) [1] TRUE FALSE FALSE FALSE
【解决方案4】:

OP 显然只要求检查:

我需要说明“日期”列是日期类型

那么 R 附带了多少个日期类?正好两个:DatePOSIXt不包括它们的派生词,如 POSIXctPOSIXlt)。

所以我们可以检查一下,让它比已经给出的答案更可靠:

is.Date <- function(x) {
  inherits(x, c("Date", "POSIXt"))
}

尽其所能。

is.Date(as.Date("2020-02-02"))
#> [1] TRUE
is.Date(as.POSIXct("2020-02-02"))
#> [1] TRUE
is.Date(as.POSIXlt("2020-02-02"))
#> [1] TRUE

如果您想知道列是否可以成功可转换/强制 为 Date 类型,那是另一个问题。这是按照要求:'告诉 [...] 是 Date 类型'。

【讨论】:

  • 如果输入是日期,它会很好地工作。你试过is.Date(as.Date("blablabla"))吗?预期的输出应该是 FALSE 而不是错误。
  • 不同意,错误来自as.Date(),而不是来自is.Date()。如果输入是日期,则此功能对于检查确实是可靠的。就像 OP 要求的那样。
  • 那么你应该把函数名改成is.typeof.Date()以避免混淆。
  • 不同意,is.numeric()is.logical()is.data.frame() 等也不是这种情况。is.*() 函数仅用于检查 S3 类,我的 is.Date() 就是这样做的好吧:)
  • 不同意,is.* 函数是为了在自动化处理中提供直接的答案。错误是自动化处理中可接受的答案吗?想想这一切的总体目标。错误是否在您的目标范围内?
【解决方案5】:

为了处理日期,我使用一个函数来识别字符串是否为日期,如果是,则将它们转换为预定义的格式(在这种情况下,我选择 ''%d/%m/%Y'):

standarDates <- function(string) {
  patterns = c('[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]','[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]','[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]')
  formatdates = c('%Y/%m/%d','%d/%m/%Y','%Y-%m-%d')
  standardformat='%d/%m/%Y'
  for(i in 1:3){
    if(grepl(patterns[i], string)){
      aux=as.Date(string,format=formatdates[i])
      if(!is.na(aux)){
        return(format(aux, standardformat))
      }
    }
  }
  return(FALSE)
}

假设你有向量

a=c("2018-24-16","1587/03/16","fhjfmk","9885/04/16")

> sapply(a,standarDates)
2018-24-16   1587/03/16       fhjfmk   9885/04/16 
  "FALSE"   "16/03/1587"      "FALSE" "16/04/9885"

用命令

"FALSE"%in%sapply(a,standarDates)
[1] True

你可以判断所有元素是否都是日期。

此功能的优点是您可以根据正在使用的数据添加更多模式和日期格式,并以标准格式结束所有这些日期。 (缺点是这不是问题所要问的)

希望对你有帮助

【讨论】:

    【解决方案6】:

    我根据这里的答案创建的功能,现在正在使用

    is.Date <- function(date) {
      if (sapply(date, function(x)
         ! all(is.na(as.Date(
         as.character(x),
         format = c("%d/%m/%Y", "%d-%m-%Y", "%Y/%m/%d", "%Y-%m-%d")
         ))))) {
        return(TRUE)
      } else{
        return(FALSE)
      }
    }
    

    【讨论】:

    • 你能否提供一些例子来看看这个函数是如何工作的?也许在函数中抛出一些字符串以查看发生了什么。当你确实让我知道为你投票时
    • 最好举一些例子,如果出现一些警告
    【解决方案7】:

    我将参考一个简单的例子,希望它可以概括。 说你有约会

    d1<-Sys.Date()
    d1
    

    “2020-02-12”

    deparse(d1)
    

    "结构(18304, class= \"日期\")"

    这样

    grep("Date",deparse(d1))>=1
    

    是的

    交替使用

    class(d1)
    

    “日期”

    【讨论】:

      【解决方案8】:

      这是我的做法。大部分时间都可以工作,但需要改进

      MissLt <- function(x, ratio = 0.5){
        sum(is.na(x))/length(x) < ratio
      }
      
      
      IS.Date  <- function(x, addformat = NULL, exactformat = NULL){
        if (is.null(exactformat)){
          format = c("%m/%d/%Y", "%m-%d-%Y","%Y/%m/%d" ,"%Y-%m-%d", addformat) 
          y <- as.Date(as.character(x),format= format)
          MissLt(y,ratio = 1-(1/length(y)))}
        else{
          y <- as.Date(as.character(x),format= exactformat)
          MissLt(y,ratio = 1-(1/length(y)))}
      }
      sapply(data, IS.Date)
      

      【讨论】:

      • 另一个可以考虑的包叫做“anytime”
      • 这是一个检查列是否可以成功转换/强制转换为 Date 类型的解决方案,这不是问题。
      • 和thelatemail的回答基本一样,我只是添加了更多格式...
      • 太棒了!这是很好的代码。但这是另一个问题的答案,例如“我如何尝试不同的格式来在 R 中创建有效的日期类型?”。问的问题是'我需要一些东西来告诉'日期'列是日期类型',所以只要求检查。不过你的建议不错,继续努力!
      猜你喜欢
      • 2020-12-19
      • 2011-02-19
      • 2022-10-04
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      相关资源
      最近更新 更多