使用 pyspark 计算日期之间的天数,忽略周末

Wil*_*lem 4 python pyspark

如何使用 计算忽略周末的两个日期之间的天数pyspark

这与这里的问题完全相同,只是我需要这样做pyspark

我尝试使用udf

import numpy as np
from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType

@udf(returnType=IntegerType())
def dateDiffWeekdays(end, start):
    return int(np.busday_count(start, end)) # numpy returns an `numpy.int64` type.

Run Code Online (Sandbox Code Playgroud)

使用此 udf 时,我收到一条错误消息:

ModuleNotFoundError:没有名为“numpy”的模块

有谁知道如何解决这个问题?udf或者更好的是,在没有原生的情况下解决这个问题pyspark

编辑:我已经numpy安装了。在 a 之外udf它工作得很好。

wer*_*ner 7

对于 Spark 2.4+,可以在不使用 numpy 或 udf 的情况下获取天数。使用内置的SQL 函数就足够了。

大致遵循这个答案我们可以

  1. 使用序列创建包含开始和结束之间所有日期的日期数组
  2. 将单日转换为保存该天及其星期几值的结构
  3. 过滤掉星期六和星期日的日子
  4. 获取剩余数组的大小
#create an array containing all days between begin and end
(df.withColumn('days', F.expr('sequence(begin, end, interval 1 day)'))
#keep only days where day of week (dow) <= 5 (Friday)
.withColumn('weekdays', F.expr('filter(transform(days, day->(day, extract(dow_iso from day))), day -> day.col2 <=5).day')) 
#count how many days are left
.withColumn('no_of_weekdays', F.expr('size(weekdays)')) 
#drop the intermediate columns
.select('begin', 'end', 'no_of_weekdays') 
.show(truncate=False))
Run Code Online (Sandbox Code Playgroud)

输出:

+----------+----------+--------------+
|begin     |end       |no_of_weekdays|
+----------+----------+--------------+
|2020-09-19|2020-09-20|0             |
|2020-09-21|2020-09-24|4             |
|2020-09-21|2020-09-25|5             |
|2020-09-21|2020-09-26|5             |
|2020-09-21|2020-10-02|10            |
|2020-09-19|2020-10-03|10            |
+----------+----------+--------------+
Run Code Online (Sandbox Code Playgroud)

对于 Spark <= 2.3,您必须使用 udf。如果 numpy 是一个问题,可以使用受此答案启发的解决方案。

from datetime import timedelta
@F.udf
def dateDiffWeekdays(end, start):
    daygenerator = (start + timedelta(x) for x in range((end - start).days + 1))
    return sum(1 for day in daygenerator if day.isoweekday() <= 5)

df.withColumn("no_of_weekdays", dateDiffWeekdays(df.end, df.begin)).show()
Run Code Online (Sandbox Code Playgroud)

  • 值得将此答案的第一部分添加到[获取 Spark DataFrame 中两个日期之间的所有日期](/sf/ask/3622150521/ Between-two-dates-在 Spark 数据框中)。另请注意,这仅适用于 Spark 2.4+ (2认同)