简体   繁体   English

R中年月日时间串连题

[英]Concatenate year, month, day and time problem in R

I have these columns in my dataframe, df :我的 dataframe, df中有这些专栏:

year month day hour minute
2013 1     7   21   54
2013 3     20  13   59
2013 1     3   18   40

  .. cols(
  ..   year = col_double(),
  ..   month = col_double(),
  ..   day = col_double(),
  ..   hour = col_double(),
  ..   minute = col_double(),

I want to have a new column, datetime :我想要一个新列datetime

datetime
2013/1/7   21:54
2013/3/20  13:59
2013/1/3   18:40

I have tried this:我试过这个:

library(readr)
library(dplyr)

df$datetime <- with(df, as.POSIXct(paste(year, month, day, hour, minute), 
                                 format = "%Y/%m/%d %H:%M:%S"))

and this:还有这个:

df$DT <- as.POSIXct((paste(df$year, df$month, df$day, df$hour, df$minute)), format="%Y/%m/%d %H:%M:%S")

However, it gives me all NA values.但是,它给了我所有的NA值。

  • I could merge just the year, month and day with as.Date() though.不过,我可以将年、月和日与 as.Date() 合并。 How can I add times to it?我怎样才能增加时间呢?

  • Also, how can I sort by datetime later on?另外,以后如何按日期时间排序?

You could use your original syntax, but make sure you put the right separators between the various components of the date-time:您可以使用原始语法,但请确保在日期时间的各个部分之间放置正确的分隔符:

dat <- tibble::tribble(
  ~year, ~month, ~day, ~hour, ~minute,
2013, 1,     7,   21,   54,
2013, 3,     20,  13,   59,
2013, 1,     3,   18,   40)


dat$datetime <- with(dat, as.POSIXct(paste0(year, "/", month, "/", day, " ", hour, ":", minute, ":00"), 
                                   format = "%Y/%m/%d %H:%M:%S"))

dat
#> # A tibble: 3 × 6
#>    year month   day  hour minute datetime           
#>   <dbl> <dbl> <dbl> <dbl>  <dbl> <dttm>             
#> 1  2013     1     7    21     54 2013-01-07 21:54:00
#> 2  2013     3    20    13     59 2013-03-20 13:59:00
#> 3  2013     1     3    18     40 2013-01-03 18:40:00

Created on 2022-12-06 by the reprex package (v2.0.1)reprex package (v2.0.1) 创建于 2022-12-06

When you tell as.POSIXct() that the format is "%Y/%m/%d %H:%M:%S" , it expects to see a string that looks like that (eg, "2013/01/03 13:59:00" ).当您告诉as.POSIXct()格式为"%Y/%m/%d %H:%M:%S"时,它希望看到一个看起来像这样的字符串(例如, "2013/01/03 13:59:00" )。 Your syntax was pasting them together with just spaces, making something like "2013 01 03 13 59" so when as.POSIXct() tried to parse the string, it didn't see the expected separators.您的语法只是将它们与空格粘贴在一起,形成类似于"2013 01 03 13 59"的内容,因此当as.POSIXct()尝试解析字符串时,它没有看到预期的分隔符。 You could also have gotten the same result by maintaining your original paste() specification and changing the format:您也可以通过维护原始paste()规范并更改格式来获得相同的结果:

library(dplyr)
dat <- tibble::tribble(
  ~year, ~month, ~day, ~hour, ~minute,
  2013, 1,     7,   21,   54,
  2013, 3,     20,  13,   59,
  2013, 1,     3,   18,   40)


dat$datetime <- with(dat, as.POSIXct(paste(year,  month,  day, hour, minute), 
                                     format = "%Y %m %d %H %M"))

arrange(dat, desc(datetime))
#> # A tibble: 3 × 6
#>    year month   day  hour minute datetime           
#>   <dbl> <dbl> <dbl> <dbl>  <dbl> <dttm>             
#> 1  2013     3    20    13     59 2013-03-20 13:59:00
#> 2  2013     1     7    21     54 2013-01-07 21:54:00
#> 3  2013     1     3    18     40 2013-01-03 18:40:00

Created on 2022-12-06 by the reprex package (v2.0.1)reprex package (v2.0.1) 创建于 2022-12-06

The easiest way is to use make_datetime from lubridate .最简单的方法是使用make_datetime中的lubridate This function accepts the double inputs directly so you don't need to concatenate into a string yourself.这个 function 直接接受double输入,所以你不需要自己连接成一个字符串。

library(dplyr)
library(lubridate)

df |> mutate(datetime = make_datetime(year, month, day, hour, minute))

Output: Output:

# A tibble: 3 × 6
   year month   day  hour minute datetime           
  <dbl> <dbl> <dbl> <dbl>  <dbl> <dttm>             
1  2013     1     7    21     54 2013-01-07 21:54:00
2  2013     3    20    13     59 2013-03-20 13:59:00
3  2013     1     3    18     40 2013-01-03 18:40:00

Data:数据:

library(readr)

df <- read_table("year month day hour minute
                 2013 1     7   21   54
                 2013 3     20  13   59
                 2013 1     3   18   40")

Update : This can also be sorted using arrange :更新:这也可以使用arrange进行排序:

library(dplyr)
library(lubridate)

df |> 
  mutate(datetime = make_datetime(year, month, day, hour, minute)) |>
  arrange(datetime)

Output: Output:

# A tibble: 3 × 6
   year month   day  hour minute datetime           
  <dbl> <dbl> <dbl> <dbl>  <dbl> <dttm>             
1  2013     1     3    18     40 2013-01-03 18:40:00
2  2013     1     7    21     54 2013-01-07 21:54:00
3  2013     3    20    13     59 2013-03-20 13:59:00

An alternative to @DaveArmstrong's answer, using tidyverse :使用tidyverse替代@DaveArmstrong 的答案:

suppressPackageStartupMessages({
  library(tidyr)
  library(lubridate)
  library(dplyr)
})
#> Warning: package 'lubridate' was built under R version 4.2.2
#> Warning: package 'timechange' was built under R version 4.2.2

test <- tibble::tribble(
  ~year, ~month, ~day, ~hour, ~minute,
  2013, 1,     7,   21,   54,
  2013, 3,     20,  13,   59,
  2013, 1,     3,   18,   40)

test
#> # A tibble: 3 × 5
#>    year month   day  hour minute
#>   <dbl> <dbl> <dbl> <dbl>  <dbl>
#> 1  2013     1     7    21     54
#> 2  2013     3    20    13     59
#> 3  2013     1     3    18     40

test |> 
  unite(col = datetime, everything(), sep = "-", remove = FALSE) |> 
  mutate(
    datetime = ymd_hm(datetime)
  )
#> # A tibble: 3 × 6
#>   datetime             year month   day  hour minute
#>   <dttm>              <dbl> <dbl> <dbl> <dbl>  <dbl>
#> 1 2013-01-07 21:54:00  2013     1     7    21     54
#> 2 2013-03-20 13:59:00  2013     3    20    13     59
#> 3 2013-01-03 18:40:00  2013     1     3    18     40

Created on 2022-12-06 with reprex v2.0.2创建于 2022-12-06,使用reprex v2.0.2

library(magrittr)

df <- tibble::tribble(
  
  ~year, ~month, ~day, ~hour,  ~minute,
  2013, 1,     7, 21,   54,
  2013, 3,     20,  13,   59,
  2013, 1,     3, 18,   40,
  
)

df %>% 
  # pad date elements with leading zeros so parsing works out
  dplyr::mutate(month = stringr::str_pad(month, width = 2, pad = "0"),
                day = stringr::str_pad(day, width = 2, pad = "0")) %>% 
  # parse as actual datetime
  dplyr::mutate(datetime = lubridate::ymd_hm(paste0(year, month, day, hour, minute)))
#> # A tibble: 3 x 6
#>    year month day    hour minute datetime           
#>   <dbl> <chr> <chr> <dbl>  <dbl> <dttm>             
#> 1  2013 01    07       21     54 2013-01-07 21:54:00
#> 2  2013 03    20       13     59 2013-03-20 13:59:00
#> 3  2013 01    03       18     40 2013-01-03 18:40:00

Created on 2022-12-06 by the reprex package (v2.0.1)reprex package (v2.0.1) 创建于 2022-12-06

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM