日期时间转换并提取时间

28

想要将Time的类别更改为POSIXlt,并仅提取小时、分钟和秒钟

str(df3$Time)
chr [1:2075259] "17:24:00" "17:25:00" "17:26:00" "17:27:00" ...

使用了strptime函数

df33$Time <- strptime(df3$Time, format = "%H:%M:%S") 

这将给出追加的日期/时间

> str(df3$Time)
 POSIXlt[1:2075259], format: "2015-08-07 17:24:00" "2015-08-07 17:25:00" "2015-08-07 17:26:00" ...

想从POSIXlt类中提取时间,而不改变其类型。可以使用strftime函数。

df3$Time <- strftime(df3$Time, format = "%H:%M:%S") 

但这将类转换回 "char" 类型 -

> class(df3$Time)
[1] "character"

我该如何仅提取类为POSIX或数字的时间?

6个回答

29
如果您的数据是
a <- "17:24:00"

b <- strptime(a, format = "%H:%M:%S")

你可以使用lubridate来获得一个integer类的结果。

library(lubridate)
hour(b)
minute(b)

# > hour(b)
# [1] 17
# > minute(b)
# [1] 24


# > class(minute(b))
# [1] "integer"

然后你可以使用它们进行组合

# character
paste(hour(b),minute(b), sep=":")

# numeric
hour(b) + minute(b)/60

例如。

如果您想对数据进行进一步操作,我不建议这样做。然而,如果您想绘制结果,这样做可能会很方便。


5
使用基本的R函数,你不需要用lubridate来创建整数:as.integer(format(Sys.time(), "%H%M%S"))可以很好地完成这个任务。请注意,这里不包括任何解释性的内容。 - Dirk Eddelbuettel
8
那么为什么你没有发布它呢?这是原文作者的问题之一。 - rmuc8

13

一个日期时间(datetime)对象包含日期和时间,您无法提取'仅时间(just time)'。因此,您需要考虑您想要什么:

  • POSIXlt是一个日期时间(Datetime)表示(作为组件列表)
  • POSIXct是另一种日期时间(Datetime)表示(作为紧凑的数字)

两者都不省略日期部分。一旦您拥有有效对象,您可以选择仅显示(display)时间。但您无法使日期部分从表示(representation)中消失。


谢谢您的及时回复,Dirk。那么您能否举个例子,如何在数据框中仅显示HHMMSS? - Antex
尝试了两种方法 - 它们都像上面所述一样将类转换回字符...这是挑战。.> str(df3) 'data.frame': 2075259 obs. of 9 variables: $ Date : 日期, 格式: "2006-12-16" "2006-12-16" ... $ Time : chr "17:24:00" "17:25:00" "17:26:00" "17:27:00" ... - Antex
我认为你仍然不理解。Datetime对象包含它所说的内容。一个短字符字符串包含格式化信息。你可以使用前者构建后者。但后者仍然不会是Datetime对象。 - Dirk Eddelbuettel
我理解datetime对象是什么。从字符“17:20:00”开始,我正在使用strptime函数将类转换。但该函数附加了今天的日期str(df3$Time)$ Time:POSIXlt,格式:“2015-08-07”2015-08-07 17:20:00” - 我不想在表格中显示今天的日期。只要时间!我的问题再次不是Datetime对象是什么,而是为什么我不能仅提取HHMMSS而不更改类别为字符 - 您是否意味着这是不可能的? - Antex
2
尝试执行 format(Sys.time(), "%H%M%S") 命令,它在几秒前为我提供了 "073007" 的结果,因为我所在的地方现在是早上7:30。是的,这个命令会返回字符值,因为 strftime()format() 函数都是如此。现在让我们停下来,我建议你退后一步,阅读充足的文档。祝好运! - Dirk Eddelbuettel

9
一个"现代化"的tidyverse方法是使用hms::as_hms()
例如:
library(tidyverse)
library(hms)

as_hms(1)
#> 00:00:01
as_hms("12:34:56")
#> 12:34:56

或者,以您的示例数据为例:

x <- as.POSIXlt(c("17:24:00", "17:25:00", "17:26:00", "17:27:00"), format = "%H:%M:%S")

x
#>[1] "2021-04-10 17:24:00 EDT" "2021-04-10 17:25:00 EDT" "2021-04-10 17:26:00 EDT" "2021-04-10 17:27:00 EDT"

as_hms(x)
# 17:24:00
# 17:25:00
# 17:26:00
# 17:27:00

相关文档也可参见此处: https://hms.tidyverse.org/reference/hms.html


7

您也可以使用chron包仅提取一天中的时间:

library(chron) 

# current date/time in POSIXt format as an example
timenow <- Sys.time()

# create chron object "times"
onlytime <- times(strftime(timenow,"%H:%M:%S"))

> onlytime
[1] 14:18:00
> onlytime+1/24
[1] 15:18:00
> class(onlytime)
[1] "times"

7
这是一个关于从日期时间对象中获取时间部分的成语。我使用lubridate中的floor_date()获取时间戳午夜并取时间戳与当天午夜之间的差值。我创建并存储了一个hms对象,该对象由lubridate提供(我相信),因为该类具有易于阅读的hh:mm:ss格式化,但基础值是以秒为单位的数字值。以下是我的代码:
library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date

# Create timestamps
#
# Get timepart by subtacting the timestamp from it's floor'ed date, make sure
# you convert to seconds, and then cast to a time object provided by the
# `hms` package.
# See: https://www.rdocumentation.org/packages/hms/versions/0.4.2/topics/hms
dt <- tibble(dt=c("2019-02-15T13:15:00", "2019-02-19T01:10:33") %>% ymd_hms()) %>%
  mutate(timepart = hms::hms(as.numeric(dt - floor_date(dt, "1 day"), unit="secs")))

# Look at result
print(dt)
#> # A tibble: 2 x 2
#>   dt                  timepart
#>   <dttm>              <time>  
#> 1 2019-02-15 13:15:00 13:15   
#> 2 2019-02-19 01:10:33 01:10

# `hms` object is really a `difftime` object from documentation, but is made into a `hms`
# object that defaults to always store data in seconds.
dt %>% pluck("timepart") %>% str()
#>  'hms' num [1:2] 13:15:00 01:10:33
#>  - attr(*, "units")= chr "secs"

# Pull off just the timepart column
dt %>% pluck("timepart")
#> 13:15:00
#> 01:10:33

# Get numeric part.  From documentation, `hms` object always stores in seconds.
dt %>% pluck("timepart") %>% as.numeric()
#> [1] 47700  4233

此内容由reprex软件包(v0.2.1)于2019年02月15日创建。


1
回想起来,我本可以更好地表达问题。当时我还没有太多经验。但是@mpettis恰到好处地回答了我的问题。谢谢! - Antex
1
谢谢!你最初发布的方式正是我所考虑的,所以我对措辞没有任何批评。我发布这篇文章是因为在得到答案之前我来到了这篇文章,对其他答案不完全满意,发现了hms包,并决定留下这个答案供后人参考。 - mpettis

2

如果您想要使用POSIX格式,唯一的方法是将其保留原样,并在每次显示时仅提取“时间”部分。但内部始终是日期+时间。 然而,如果您想要数字格式,可以将其简单地转换为数字。 例如,要获取自该日开始的秒数作为时间:

df3$Time=df3$Time$sec + df3$Time$min*60 + df3$Time$hour*3600

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接