使用正则表达式将列拆分为2

时间:2017-04-17 08:43:07

标签: r dplyr tidyr lubridate

我的数据框由以下格式的时间组成:

<select>    
     <c:forEach var="entry" items="${pageScope.map}">
        <option value="${entry.key}">${entry.value}</option>
     </c:forEach>
</select>

我想将其更改为标准格式,即使用冒号的16:55:00,但在df<-data.frame(time=c("1655","1055","1123","1505")) # time # 1 1655 # 2 1055 # 3 1123 # 4 925 包中使用函数hms将无效。

我正在考虑将lubridate列分成2,以便我有:

time

然后使用# time1 time2 # 1 16 55 # 2 10 55 # 3 11 23 # 4 9 25 作为分隔符将它们组合回来:

:

但是,我不确定如何做(特别是与Regex打交道)。我试过了:

#   time
# 1 16:55
# 2 10:55
# 3 11:23
# 4 09:25

当然,这不起作用。

2 个答案:

答案 0 :(得分:2)

我们可以使用sprintf将3位数字转换为4位数,方法是在开头添加0,然后使用sub,我们在开头匹配两个字符并作为一组捕获({{ 1}})并将其替换为后引用((.{2})),后跟\\1

:

或其他选项df$time <- sub("^(.{2})", "\\1:", sprintf("%04d", as.integer(as.character(df$time)))) df$time #[1] "16:55" "10:55" "11:23" "09:25" 来自str_pad

stringr

如果我们更喜欢library(stringr) sub("(.{2})$", ":\\1", str_pad(df$time, 4, "left", pad = "0")) #[1] "16:55" "10:55" "11:23" "09:25" tidyverse如果我们首先使用separate/unite

mutate,也可以有效
sprintf

library(tidyverse) df %>% mutate(time = sprintf("%04d", as.integer(as.character(time)))) %>% separate(time, into = c("time1", "time2"), sep=2) %>% unite(time, time1, time2, sep=":") # time #1 16:55 #2 10:55 #3 11:23 #4 09:25

中的str_pad/str_replace
stringr

数据

df %>%
   mutate(time = str_pad(time, 4, "left", pad = "0"),
          time = str_replace(time, "(.{2})", "\\1:"))
#   time
#1 16:55
#2 10:55
#3 11:23
#4 09:25

注意:默认情况下,使用df <- data.frame(time=c("1655","1055","1123","925")) 创建data.frame而不使用stringsAsFactors会使stringsAsFactors=TRUE列成为factor,并使用{转换为integer {1}}用作as.integer(as.character

的输入

答案 1 :(得分:1)

如果您确实希望使用lubridate将时间存储为Period,则可以使用以下内容

df<-data.frame(time=c("1655","1055","1123","1505","955"))
df$time2 <- hm(gsub("(.{2}$)",":\\1",df$time))

gsub插入&#34;:&#34;在最后两个字符之前

来自hm

lubridate会将其转换为Period个对象。