合并两列(日期时间)转换成一个中的R

问题描述:

我有在“DyStart”和“DyEnd”错误条目的啤酒数据帧....合并两列(日期时间)转换成一个中的R

dataframe

ID DyStart   DyEnd    TmStart  TmEnd 
1 04.12.2017  04.12.2017  10:10:00 10:50:00 
2 01.12.2017  01.12.2017  12:27:00 16:29:00 
3 27.11.2017  27.11.2017  14:31:00 15:08:00 
4 07.12.2017 13:26 07.12.2017 13:26  

我想“DyStart”和“DyEnd”列中的所有日期以及“TmStart”和“TmEnd”中的所有日期。我对日期没有任何问题......

df$DyStart <- format(as.POSIXct(df$Dyformat,format="%d.%m.%Y"),"%d.%m.%Y") 

但是我有随时间的问题。我试图创建一个新的列,并与旧列合并...

df$TmStartNew <- format(as.POSIXct(df$DyStart,format="%d.%m.%Y %H:%M"),"%H:%M:%S") 

df$TmStart <- ifelse(is.na(df$TmStart), df$TmStartNew, df$TmStart) 

我想指出错误的东西,但我总是得到“数字”或“整数”回来,我不能给机会的格式回到H:M:S

如果有人知道解决方案,我将非常感谢!

+0

请分享使用'dput()'重复的例子。在上面的例子中,是时空/ NA的第四个条目? – Onyambu

+0

您的目标是更正“TmStart”和“TmEnd”中来自“DyStart”和“DyEnd”列的值的“NA”值是否正确? – MKR

有很多方法可以完成它。但我更愿意按照OP所考虑的步骤达到预期的结果。

看来修改都不在,这是造成在OP问题预期的顺序进行。

让我在OP使用相同的例子来说明。

s <- "ID, DyStart,   DyEnd,    TmStart,  TmEnd 
1, 04.12.2017,  04.12.2017,  10:10:00, 10:50:00 
2, 01.12.2017,  01.12.2017,  12:27:00, 16:29:00 
3, 27.11.2017,  27.11.2017,  14:31:00, 15:08:00 
4, 07.12.2017 13:26, 07.12.2017 13:26" 

#Create df as used in OP 
df <- read.delim(textConnection(s), header = TRUE, sep = ",", 
strip.white = TRUE, stringsAsFactors = FALSE) 
#data looks as 
> df 
    ID   DyStart   DyEnd TmStart TmEnd 
1 1  04.12.2017  04.12.2017 10:10:00 10:50:00 
2 2  01.12.2017  01.12.2017 12:27:00 16:29:00 
3 3  27.11.2017  27.11.2017 14:31:00 15:08:00 
4 4 07.12.2017 13:26 07.12.2017 13:26 

#First create new columns with Time part from corresponding Date column 
df$TmStartNew <- format(as.POSIXct(df$DyStart,format="%d.%m.%Y %H:%M"),"%H:%M:%S") 
df$TmEndNew <- format(as.POSIXct(df$DyEnd,format="%d.%m.%Y %H:%M"),"%H:%M:%S") 

#Replace valid values from new columns in original Tm columns 
df$TmStart <- ifelse(!is.na(df$TmStartNew), df$TmStartNew, df$TmStart) 
df$TmEnd <- ifelse(!is.na(df$TmEndNew), df$TmEndNew, df$TmEnd) 

#Now modify Date columns to remove time part 
df$DyStart <- format(as.POSIXct(df$DyStart,format="%d.%m.%Y"),"%d.%m.%Y") 
df$DyEnd <- format(as.POSIXct(df$DyEnd,format="%d.%m.%Y"),"%d.%m.%Y") 

#data frame will now contain 
> df 
    ID DyStart  DyEnd TmStart TmEnd TmStartNew TmEndNew 
1 1 04.12.2017 04.12.2017 10:10:00 10:50:00  <NA>  <NA> 
2 2 01.12.2017 01.12.2017 12:27:00 16:29:00  <NA>  <NA> 
3 3 27.11.2017 27.11.2017 14:31:00 15:08:00  <NA>  <NA> 
4 4 07.12.2017 07.12.2017 13:26:00 13:26:00 13:26:00 13:26:00 

一旦现在可以删除TmStartNew & TmEndNew列。

截至顶部提到的这个方法已经在同一条线上的OP的创建成功,但也有其他的方法来达到同样的效果。

+0

@Michele有什么问题? – MKR

+1

坦克的帮助!在替换origianl Tm colums中新列的有效值之前,我必须将Tm colums设置为.character,现在它完美无缺! – Michele

+0

...对不起,第一条评论消失得太快了。当我在寻找问题并写下评论时,我被打断了。在第一次尝试TmEnd后,例如看起来像这样(“10”,“44”,“41”,13:26:00)而不是(“10:50:00”,“16:29:00”,“15 :08:00“,”13:26:00“)。再次感谢你的帮助! – Michele

您可以使用mutatedplyr包从lubridate包添加新列和dmy_hms粘贴日期和时间在一起后的字符串转换日期时间。

它应该是这样的:

library(dplyr) 
library(lubridate) 

df %>% 
    mutate(tm_start_new = lubridate::dmy_hms(paste(DyStart, TmStart)), 
     tm_end_new = lubridate::dmy_hms(paste(DyEnd, TmEnd))) 

这将使你:

# A tibble: 3 x 7 
     ID DyStart  DyEnd TmStart TmEnd  tm_start_new   tm_end_new 
    <fctr>  <fctr>  <fctr> <fctr> <fctr>    <dttm>    <dttm> 
1  1 04.12.2017 04.12.2017 10:10:00 10:50:00 2017-12-04 10:10:00 2017-12-04 10:50:00 
2  2 01.12.2017 01.12.2017 12:27:00 16:29:00 2017-12-01 12:27:00 2017-12-01 16:29:00 
3  3 27.11.2017 27.11.2017 14:31:00 15:08:00 2017-11-27 14:31:00 2017-11-27 15:08:00 

注:我转换数据帧的tibble,这样你可以看到类实际上是一个datetime对象。

您可以创建一个索引与grepl,可找到DyStartDyEnd有充分的日期:

i1 <- !grepl('\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}', df$DyStart) 
i2 <- !grepl('\\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}', df$DyEnd) 

然后你就可以用正确的人替代其它值:

df$DyStart[i1] <- paste(df$DyStart[i1], df$TmStart[i1]) 
df$DyEnd[i1] <- paste(df$DyEnd[i1], df$TmEnd[i1]) 

接下来,你需要粘贴:00到其他线路:

df$DyStart[!i1] <- paste0(df$DyStart[!i1], ':00') 
df$DyEnd[!i2] <- paste0(df$DyEnd[!i2], ':00') 

现在,您可以将列于日期格式:

df[2:3] <- lapply(df[2:3], function(x) as.POSIXct(x, format = '%d.%m.%Y %H:%M:%S')) 

结果:

> df 
    ID    DyStart    DyEnd TmStart TmEnd 
1 1 2017-12-04 10:10:00 2017-12-04 10:50:00 10:10:00 10:50:00 
2 2 2017-12-01 12:27:00 2017-12-01 16:29:00 12:27:00 16:29:00 
3 3 2017-11-27 14:31:00 2017-11-27 15:08:00 14:31:00 15:08:00 
4 4 2017-12-07 13:26:00 2017-12-07 13:26:00     

为了以它们转换分开你的榜样的最后一排的日期和时间进入日期和时间,你可以按照这个例子:

你的数据是

data <- read.table(text= 
"'ID' 'DyStart' 'DyEnd' 'TmStart' 'TmEnd' 
'1' '04.12.2017' '05.12.2017' '10:10:00' '10:50:00' 
'2' '01.12.2017' '01.12.2017' '12:27:00' '16:29:00' 
'3' '27.11.2017' '27.11.2017' '14:31:00' '15:08:00' 
'4' '07.12.2017 13:26' '07.12.2017 13:26' '' ''", stringsAsFactors=F, header=T) 

功能定义和使用,以清洁的日期和时间:

fn_date <- function(columnDate){ 
columnDate <- ifelse(lapply(strsplit(columnDate, " "), length)==2, 
        unlist(strsplit(columnDate, " ")[lapply(strsplit(columnDate, " "), length)==2])[1], 
        columnDate) 
return(columnDate) 
} 

fn_time <- function(columnDate, columnTime){ 
columnTime <- ifelse(lapply(strsplit(columnDate, " "), length)==2, 
        paste0(unlist(strsplit(columnDate, " ")[lapply(strsplit(columnDate, " "), length)==2])[2],":00"), 
        columnTime) 
return(columnTime) 
} 

data$TmStart <- fn_time(data$DyStart, data$TmStart) 
data$TmEnd <- fn_time(data$DyEnd, data$TmEnd) 
data[,2:3] <- lapply(data[,2:3], fn_date) 

并转换列到他们指定的格式与lubridate

library(lubridate) 
data[,2:3] <- lapply(data[,2:3], dmy) 
data[,4:5] <- lapply(data[,4:5], hms) 

结果的帮助是:

ID DyStart  DyEnd TmStart  TmEnd 
1 1 2017-12-04 2017-12-05 10H 10M 0S 10H 50M 0S 
2 2 2017-12-01 2017-12-01 12H 27M 0S 16H 29M 0S 
3 3 2017-11-27 2017-11-27 14H 31M 0S 15H 8M 0S 
4 4 2017-12-07 2017-12-07 13H 26M 0S 13H 26M 0S 

我会写两个小功能,使用您的问题:

#Function to extract time from the dates and merge it with the time column: 
    Extract_Time=function(DATE,TIME){ 
    where=grep("\\s",DATE) 
    DATE[where]=paste0(DATE[where],":00")#Am assuming all the data you have does not contain seconds 
    ifelse(is.na(TIME),format(strptime(DATE,'%d.%m.%Y %H:%M:%S'),'%H:%M:%S'),TIME) 
} 

#Function for the date column: 
DATE=function(x)as.Date(x,'%d.%m.%Y') 
transform(dat1,DyStart=DATE(DyStart), 
      DyEnd=DATE(DyEnd), 
      TmStart=Extract_Time(DyStart,TmStart), 
      TmEnd=Extract_Time(DyEnd,TmEnd)) 

    ID DyStart  DyEnd TmStart TmEnd 
1 1 2017-12-04 2017-12-04 10:10:00 10:50:00 
2 2 2017-12-01 2017-12-01 12:27:00 16:29:00 
3 3 2017-11-27 2017-11-27 14:31:00 15:08:00 
4 4 2017-12-07 2017-12-07 13:26:00 13:26:00 
5 5 2017-12-08 2017-12-08 15:26:00 16:26:00 

中使用的数据:

dat1=read.table(text="ID DyStart DyEnd TmStart TmEnd 
1 04.12.2017  04.12.2017  10:10:00 10:50:00 
2 01.12.2017  01.12.2017  12:27:00 16:29:00 
3 27.11.2017  27.11.2017  14:31:00 15:08:00 
4 '07.12.2017 13:26' '07.12.2017 13:26' NA NA  
5 '08.12.2017 15:26' '08.12.2017 16:26' NA NA ",h=T,stringsAsFactor=F)