【问题标题】:Import duration from CSV从 CSV 导入持续时间
【发布时间】:2019-10-24 12:21:17
【问题描述】:

我有一个 CSV 文件,其中包含我想导入到 R 中的通话记录,例如通话时间、被叫号码、通话时长等。

CSV 文件中“通话时长”字段的格式类似于 1d02:03:04,即 1 天 2 小时 3 分钟 4 秒。

我可以使用df.duration = pd.to_timedelta(df.duration) 轻松地将 Duration 字段转换为 Python Pandas 中的 Duration 对象。 转换后,我可以通过将开始时间与持续时间相加来获得停止时间。

我正在寻找 R 中相同的等价物将 1d02:03:04 转换为持续时间对象,以便我可以获得结束时间。

【问题讨论】:

  • 查看 R 中的 lubridate 包。有一个名为 interval 的函数。可能是您的起点
  • lubridate::as.duration
  • @Arun 欢迎来到 SO! :) 请提供最少且可重复的示例以及所需的输出。您可以使用dput() 轻松向我们展示您的数据样本。

标签: r duration


【解决方案1】:

或者,您也可以为此使用 regex(即使其他解决方案,例如 lubridate 可能更好):

首先创建模式^(\\d*)d(\\d*):?(\\d*):?(\\d*)$(可能需要适应您的格式)以提取持续时间的天数、小时数、分钟数和秒数。然后,您可以将这些信息添加到您的开始时间。

fun = function (start_time, duration) {
  # Check start_time
  if (!'POSIXct' %in% class(start_time))
    stop('Expect "start_time" to be of class "POSIXct"')

  # Regex pattern for extraction of days, hours, minutes & seconds
  pattern = '^(\\d*)d(\\d*):?(\\d*):?(\\d*)$'

  # Extract data
  days    = as.integer(gsub(pattern, '\\1', duration))
  hours   = as.integer(gsub(pattern, '\\2', duration))
  minutes = as.integer(gsub(pattern, '\\3', duration))
  seconds = as.integer(gsub(pattern, '\\4', duration))
  # Maybe add some safety measures just in case e.g. ifelse(is.na(seconds ), 0L, seconds)

  # Add (in seconds)
  final_time = start_time + seconds + minutes*60 + hours*60*60 + days*60*60*24
  return (final_time)
}

这里是一个带有向量的小例子

durations = c('1d02:03:04', '2d02:03:04', '10d02:03:04')
start_times = rep(Sys.time(), 3L)
fun(start_time = start_times, duration = durations)
# [1] "2019-06-11 11:02:19 CEST" "2019-06-12 11:02:19 CEST" "2019-06-20 11:02:19 CEST"

【讨论】:

  • 嗨 Niko.. 我期待像 python 中的单行代码。但是,您的解决方案很有帮助。谢谢。
【解决方案2】:

chron times 类将持续时间表示为天数和一天的分数。我们定义了两个函数来从我们的自定义文本格式转换为times 和从times 转换为我们的自定义文本格式。

library(chron)
text2times <- function(x) with(read.table(text = as.character(x), sep = "d", as.is = TRUE),
  V1 + times(V2))
times2text <- function(x) paste(as.integer(x), format(x %% 1), sep = "d") 

dd <- transform(d, diffdays = text2times(stop) - text2times(start),
                   difftext = times2text(text2times(stop) - text2times(start)))

给予:

       start       stop diffdays   difftext
1 1d02:03:04 2d02:03:50 1.000532 1d00:00:46

S3 自定义类 dur

这对于您的需要可能有点过头了,但我们可以定义一个 S3 类 dur 来执行此操作。

as.dur <- function(x, ...) UseMethod("as.dur")
as.dur.character <- function(x, ...) structure(text2times(x), class = c("dur", "times"))
as.dur.factor <- function(x, ...) as.dur(as.character(x))
format.dur <- function(x, ...) times2text(times(x))

# new it's easy
transform(d, diff = as.dur(stop) - as.dur(start))

给予:

       start       stop       diff
1 1d02:03:04 2d02:03:50 1d00:00:46

在 read.table 中使用 dur

我们也可以将数据直接读入dur

setAs("character", "dur", function(from) as.dur(from))

# test input - normally read from file but to keep answer self contained use string
Lines <- "start stop
1d02:03:04 2d02:03:50"

# now it's even easier
dd <- read.table(text = Lines, header = TRUE, colClasses = c("dur", "dur"))
transform(dd, diff = stop - start)
##        start       stop       diff
## 1 1d02:03:04 2d02:03:50 1d00:00:46

注意

可重现形式的样本输入:

d <- data.frame(start = "1d02:03:04", stop = "2d02:03:50")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 2015-08-31
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2011-01-15
    相关资源
    最近更新 更多