【问题标题】:Extract duration in years and months from string and convert to months从字符串中提取年和月的持续时间并转换为月
【发布时间】:2020-12-14 14:03:45
【问题描述】:

我有一个带有句点长度的字符串列,格式为"xx years yy months"。我只想以月表示这些时期,即 12 * 年数 + 月数。

一个小例子:

x = c("2 years 5 months", "10 years 10 months")

这里想要的结果分别是2 * 12 + 5 = 29 和10 * 12 + 10 = 130。


我尝试了substr 函数,但我无法处理月份和年份可能是一位数或两位数的事实。

12 * as.numeric(substr(x, 1, 2)) + as.numeric(substr(x, 6, 7)))

然后我尝试了如下sprintf,但它没有给出预期的结果。

sprintf("%1.0f", x))

【问题讨论】:

    标签: r date time substr


    【解决方案1】:

    使用正则表达式提取年数和月数,可以这样实现:

    tomonths <- function(x) {
      sum(as.numeric(regmatches(x, gregexpr("\\d+", x))[[1]]) * c(12, 1))  
    }
    tomonths("10 years 10 months")
    #> [1] 130
    

    对于您可以使用的向量,例如sapply(c("2 years 5 months", "10 years 10 months"), tomonths).

    编辑:在@thelatemail(谢谢!)的评论之后,一种矢量化且更有效的方法如下所示:

    tomonths2 <- function(x) {
      sapply(regmatches(x, gregexpr("\\d+", x)), function(x) sum(as.numeric(x) * c(12,1)) )  
    }
    

    【讨论】:

    • 但这不适用于矢量。我认为您必须像 sapply(regmatches(x, gregexpr("\\d+", x)), function(x) sum(as.numeric(x) * c(12,1)) ) 这样循环遍历每个值才能对其进行矢量化。
    • 是的。你说的对。但是你可以使用例如sapply(c("2 years 5 months", "10 years 10 months"), tomonths).
    • 确实如此,但是您不必要地运行 regmatchesgregexpr length(x) 次。
    • @thelatemail。谢谢。现在我明白你的意思了。你是完全正确的。实际上,我忽略了您第一条评论的第二部分。
    • 非常感谢!这有助于我解决问题。
    【解决方案2】:

    在您的 substr 尝试的基础上构建:几个月,您可以从字符串末尾定义 startstop 以避免根据月份和年份的位数而出现不同的开始/停止位置的问题

    as.integer(substr(x, 1, 2)) * 12 + as.integer(substr(x, nchar(x) - 8, nchar(x) - 6))
    # [1]  29 130 
    

    另一个非正则表达式替代:

    sapply(strsplit(x, " "), function(v) sum(as.integer(v[c(1, 3)]) * c(12, 1)))
    # [1]  29 130
    

    使用lubridate 便利函数:

    library(lubridate)
    time_length(duration(x), unit = "months")
    # [1]  29 130
    

    【讨论】:

    • 非常感谢! Lubridate 包帮助我处理数据。
    猜你喜欢
    • 2021-07-31
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多