Python для блоков данных получает дату окончания недели во фрейме данных - PullRequest
0 голосов
/ 03 октября 2019

Предположим, у меня есть следующий фрейм данных неделя года 2019 1 2019 2

Я хотел бы получить воскресенье недели 1 и недели 2

год недели Воскресенье
2019 120190106 2019 2 20190113

Как этого добиться?

1 Ответ

0 голосов
/ 03 октября 2019

pyspark.sql.functions имеет очень удобную функцию с именем next_day, которая делает именно то, что вы хотите. Требуется дата и день недели, который вы хотите найти. Создание правильной контрольной даты для этой функции может быть немного сложным, я сделал это так:

df.withColumn("firstDayOfYear",  to_date(concat(col("year"), lit("-1-1"))))\
    .withColumn("realtiveWeekDay", expr("date_add(firstDayOfYear, (week - 1) * 7)"))\
    .withColumn("Sunday", next_day("realtiveWeekDay", "Sun")).show()

То, что я делаю здесь, сначала создаю первый день года, а затем нахожу соответствующий день в желаемомнеделю, а затем запустить next_day, чтобы получить в следующее воскресенье. У этого подхода есть одна проблема - крайние случаи, как вы можете видеть ниже.

+----+----+--------------+---------------+----------+
|year|week|firstDayOfYear|realtiveWeekDay|    Sunday|
+----+----+--------------+---------------+----------+
|2019|   1|    2019-01-01|     2019-01-01|2019-01-06|
|2019|   2|    2019-01-01|     2019-01-08|2019-01-13|
|2019|  53|    2019-01-01|     2019-12-31|2020-01-05|
|2018|   1|    2018-01-01|     2018-01-01|2018-01-07|
|2017|   1|    2017-01-01|     2017-01-01|2017-01-08|
|2017|   2|    2017-01-01|     2017-01-08|2017-01-15|
+----+----+--------------+---------------+----------+

В 2017 году 1 января было воскресенье - поэтому я понимаю, что воскресенье первой недели, которое вы хотите найти, на самом деле 2017.1.1.1,Когда мы передали его в next_day, мы получим в следующее воскресенье после текущего. Чтобы исправить это, мы можем добавить дополнительную логику:

df.withColumn("firstDayOfYear",  to_date(concat(col("year"), lit("-1-1"))))\
    .withColumn("realtiveWeekDay", expr("date_add(firstDayOfYear, (week - 1) * 7)"))\
    .withColumn("AdjustedSunday", when(dayofweek("realtiveWeekDay") == 1, col("realtiveWeekDay")).otherwise(next_day("realtiveWeekDay", "Sun")))\
    .select("year", "week", "AdjustedSunday").show()

Это даст вам правильные результаты:


+----+----+--------------+
|year|week|AdjustedSunday|
+----+----+--------------+
|2019|   1|    2019-01-06|
|2019|   2|    2019-01-13|
|2019|  53|    2020-01-05|
|2018|   1|    2018-01-07|
|2017|   1|    2017-01-01|
|2017|   2|    2017-01-08|
+----+----+--------------+

Следует отметить, что в конце года последнийвоскресенье недели может быть в следующем году. Возможно, вы захотите обработать этот случай особым образом.

Выше код предполагает, что вы импортировали все используемые функции из pyspark.sql.functions, поэтому вы можете захотеть сделать

from pyspark.sql.functions import *
...