代码之家  ›  专栏  ›  技术社区  ›  Metadata

如何将字符串中的时间值从PT格式转换为秒?

  •  0
  • Metadata  · 技术社区  · 5 年前

    我有一个专栏: runtime 在我的json文件中,它包含一个数据为PT格式的字符串。 前任:

    { "day":"Monday","runtime":"PT45M"},
    { "day":"Tuesday","runtime":"PT1H"},
    { "day":"Wednesday","runtime":"PT4H5S"},
    { "day":"Thursday","runtime":"PT2H1M"},
    { "day":"Friday","runtime":"PT2M1S"}
    

    当我将上述文件加载到本地myql表时,Spark将其推断为字符串类型。

    >>> df.select('runtime').show()
    +--------+
    | runtime|
    +--------+
    |   PT45M|
    |   PT20M|
    |   PT15M|
    |    PT1H|
    |   PT45M|
    |   PT30M|
    |   PT15M|
    |   PT30M|
    |    PT1H|
    |   PT20M|
    |   PT45M|
    |   PT30M|
    

    现在我试图转换列的值 运行时 以PT格式转换为秒。

    在纯Python中,我能够解析PT格式字符串中的值,并从中获取值。 前任:

    >>> txt = 'PT20M'
    >>> print(int(re.search(r"(\d+)M", txt).group(1)) * 60)
    1200
    >>>
    >>> txt = 'PT1H'
    >>> print(int(re.search(r"(\d+)H", txt).group(1)) * 60 * 60)
    3600
    >>>
    >>> txt = 'PT20S'
    >>> print(int(re.search(r"(\d+)S", txt).group(1)))
    20
    >>>
    

    然后是带有(小时-分钟),(小时-秒),(分钟-秒)的字符串。 对于两种类型的字符串,第二个值可以通过 group(2) .

    例子:

    >>> txt = 'PT1H2M'
    >>> print(int(re.search(r"(\d+)H(\d+)M", txt).group(1)))
    1
    >>> print(int(re.search(r"(\d+)H(\d+)M", txt).group(2)))
    2
    >>> txt = 'PT5M34S'
    >>> print(int(re.search(r"(\d+)M(\d+)S", txt).group(1)))
    5
    >>> print(int(re.search(r"(\d+)M(\d+)S", txt).group(2)))
    34
    >>>
    

    有没有办法在我的数据帧上应用正则表达式 运行时 列,并在新列中将其值转换为秒。

    我尝试以HOUR类型的字符串开头,但遇到了如下错误:

    >>> df = df.withColumn('matched',F.when(df.runtime.rlike('(\d+)H'), int(re.search(r"(\d+)H", df.col('runtime')).group(1))*60*60).otherwise(1))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/apache-spark/3.1.1/libexec/python/pyspark/sql/dataframe.py", line 1643, in __getattr__
        raise AttributeError(
    AttributeError: 'DataFrame' object has no attribute 'col'
    >>>
    

    我想不出在专栏文章中应用这个正则表达式的方法: 运行时 然后将它们转换为秒,转换为一个新列。 有人能告诉我如何解决这个问题吗? 非常感谢您的帮助。

    0 回复  |  直到 5 年前
        1
  •  2
  •   mck    5 年前

    你可以用 regexp_extract 要提取运行时列的小时/分钟/秒部分,请执行以下操作:

    import pyspark.sql.functions as F
    
    df2 = df.withColumn(
        'runtime', 
        F.coalesce(F.regexp_extract('runtime', r'(\d+)H', 1).cast('int'), F.lit(0)) * 3600 + 
        F.coalesce(F.regexp_extract('runtime', r'(\d+)M', 1).cast('int'), F.lit(0)) * 60 + 
        F.coalesce(F.regexp_extract('runtime', r'(\d+)S', 1).cast('int'), F.lit(0))
    )
    
    df2.show()
    +---------+-------+
    |      day|runtime|
    +---------+-------+
    |   Monday|   2700|
    |  Tuesday|   3600|
    |Wednesday|  14405|
    | Thursday|   7260|
    |   Friday|    121|
    +---------+-------+
    
    推荐文章