readr::type_convert 函数破坏了时间列

4

I have the following R data frame:

zed
# A tibble: 10 x 3
   jersey_number first_name statistics.minutes
   <chr>         <chr>      <chr>             
 1 20            Marques    8:20              
 2 53            Brennan    00:00             
 3 35            Marvin     40:00             
 4 50            Justin     00:00             
 5 14            Jordan     00:00             
 6 1             Trevon     31:00             
 7 15            Alex       2:00              
 8 51            Mike       00:00             
 9 12            Javin      17:00             
10 3             Grayson    38:00     

> dput(zed)
structure(list(jersey_number = c("20", "53", "35", "50", "14", 
"1", "15", "51", "12", "3"), first_name = c("Marques", "Brennan", 
"Marvin", "Justin", "Jordan", "Trevon", "Alex", "Mike", "Javin", 
"Grayson"), statistics.minutes = c("8:20", "00:00", "40:00", 
"00:00", "00:00", "31:00", "2:00", "00:00", "17:00", "38:00")), row.names = c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

这是我从API接收到的数据格式,所有列(有约100列)最初都是字符类型。为了将其全部转换,我使用readr::type_convert(),但出现以下错误:

> zed %>% readr::type_convert()
Parsed with column specification:
cols(
  jersey_number = col_integer(),
  first_name = col_character(),
  statistics.minutes = col_time(format = "")
)
# A tibble: 10 x 3
   jersey_number first_name statistics.minutes
           <int> <chr>      <time>            
 1            20 Marques    08:20             
 2            53 Brennan    00:00             
 3            35 Marvin        NA             
 4            50 Justin     00:00             
 5            14 Jordan     00:00             
 6             1 Trevon        NA             
 7            15 Alex       02:00             
 8            51 Mike       00:00             
 9            12 Javin      17:00             
10             3 Grayson       NA 

不要抛出错误或混乱转换,我希望将这个分钟列更改为class == numeric。如果一行显示“8:20”这个列,我希望它被简单地转换为8.33。

您有任何想法吗?最好是使用type_convert继续使用的方法。


1
可能有重复问题:https://dev59.com/J2435IYBdhLWcg3w1jyV - Marian Minar
2个回答

3

library(lubridate)

不对 df 进行修改(使用你的代码)读取。

在分钟和秒数上添加小时:

df$statistics.minutes <- paste0("00:", df$statistics.minutes)

将其转换为时间类型:

df$statistics.minutes <- lubridate::hms(df$statistics.minutes)

除以60:

period_to_seconds(df$statistics.minutes) / 60

结果:

 [1]  8.333333  0.000000 40.000000  0.000000  0.000000
 [6] 31.000000  2.000000  0.000000 17.000000 38.000000

如果需要,在df中进行替换:

df$statistics.minutes <- period_to_seconds(df$statistics.minutes) / 60

我创建了下面这个帮助函数 - 基于这个结果 - 这样我就可以在不破坏管道链的情况下解决问题:

[ OP添加] :-)

fixMinutes <- function(raw.data) {

  new.raw.data <- raw.data %>%
    dplyr::mutate(statistics.minutes = paste0("00:", statistics.minutes)) %>%
    dplyr::mutate(statistics.minutes = lubridate::hms(statistics.minutes)) %>%
    dplyr::mutate(statistics.minutes = lubridate::period_to_seconds(statistics.minutes) / 60)

  return(new.raw.data)
}

zed %>% 
  ... %>% 
  fixMinutes() %>%
  ... %>%

评论我的解决方案:现在知道了更多,更好的解决方案是使用 zed %>% separate() 然后应用 as.numeric,转换为分钟并合并两列。如果将来需要将这些时间段添加到 POSIXct 元素中,则最好使用 lubridate,否则在此处不需要使用 lubridate。 - Marian Minar

2
唯一能想到的办法是先将有问题的列转换为数字格式,例如:
(zed 
   ## split stats column in two, with names unlikely to clash w/ existing
   %>% tidyr::separate(statistics.minutes,c("tmp...mins","tmp...secs"))
   ## explicitly convert
   %>% dplyr::mutate(statistics.minutes=as.numeric(tmp...mins)+as.numeric(tmp...secs)/60)
   ## throw out the temp variables
   %>% dplyr::select(-starts_with("tmp..."))
   %>% readr::type_convert()
)

我不知道这是否满足你的“继续使用type_convert”标准。通过将自定义转换函数传递给type_convert会更加优雅,但我不知道如何实现。


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