基于列值的Pyspark时间戳差异

时间:2018-09-17 22:29:15

标签: python apache-spark pyspark

我有一个带有四个时间戳列(clock_inclock_outsign_insign_out)的pyspark数据帧。我需要第三列(duration),这是两列之间的差异,但是我根据哪条规则采用的差异取决于列本身的值:

  1. 如果clock_in > clock_out,则duration = clock_in - clock_out
  2. 否则,如果为sign_in > clock_out,则为duration = sign_out - clock_out
  3. 否则,如果为clock_in > sign_in,则为duration = clock_in - clock_out
  4. 否则,duration = 0

我尝试定义UDF并将其应用如下:

from pyspark.sql import *

def calc_dur(clock_in, clock_out, sign_in, sign_out):
    if clock_in > clock_out:
        return clock_in - clock_out
    elif sign_out > clock_out:
        return sign_out - clock_out
    elif sign_in < clock_in:
        return clock_in - sign_in
    else:
        return 0

dur_udf = udf(calc_dur)

df2 = df.withColumn("duration", dur_udf(df.clock_in, df.clock_out, df.sign_in, df.sign_out))

但是,这会用Timedeltas(例如duration)填充我的Timedelta: 0 days, 1740 seconds, 0 microseconds (total: 1740 seconds)列,当我尝试过滤duration列中的行时,其值仅是非零值返回零行。

正确的方法是什么?

1 个答案:

答案 0 :(得分:1)

无需使用UDF(我认为它比较慢),您可以使用严格的Spark SQL语法来做到这一点:

列应该被强制转换为长列(如果它们是时间戳格式)。因此,您可以在每个F.col()之后添加这段代码:

F.col("...").cast(LongType())

链接到良好的SO答案:https://stackoverflow.com/a/37058395/6434448

然后我希望这段代码可以工作:

from pyspark.sql import functions as F
from pyspark.sql.types import LongType, TimestampType

df.withColumn("duration",
              F.when(F.col("clock_in") > F.col("clock_out"), F.col("clock_in") - F.col("clock_out")).otherwise(
              F.when(F.col("sign_out") > F.col("clock_out"), F.col("sign_out") - F.col("clock_out")).otherwise(
              F.when(F.col("sign_in") < F.col("clock_in"), F.col("clock_in") - F.col("sign_in")).otherwise(F.lit(0))
     ))
)