Функция разделения Pyspark на часы

Скриншот кода

 root
  |-- address: string (nullable = true)
  |-- attributes: map (nullable = true)
  |    |-- key: string
  |    |-- value: string (valueContainsNull = true)
  |-- business_id: string (nullable = true)
  |-- categories: string (nullable = true)
  |-- city: string (nullable = true)
  |-- hours: map (nullable = true)
  |    |-- key: string
  |    |-- value: string (valueContainsNull = true)
  |-- is_open: long (nullable = true)
  |-- latitude: double (nullable = true)
  |-- longitude: double (nullable = true)
  |-- name: string (nullable = true)
  |-- postal_code: string (nullable = true)
  |-- review_count: long (nullable = true)
  |-- stars: double (nullable = true)
  |-- state: string (nullable = true)

В настоящее время я работаю с набором данных Yelp, и моя цель — найти общее количество часов, в течение которых бизнес открыт в день/неделю. Из данных я могу извлечь временной диапазон для каждого дня, который выглядит как [9:0, 0:0] для определенного дня. Как я могу использовать pyspark для получения двух столбцов: один для часов работы, показывающий [9:0], и один для часов закрытия, показывающих [0:0]?

Это некоторый код, который я использовал, чтобы просто показать часы для бизнеса в наборе данных.

import pyspark.sql.functions as f
from pyspark.sql.functions import expr

df_hours = df_MappedBusiness.select(
    "business_id",
    "name",
    f.explode("hours").alias("hourDay","hourValue"), 
    f.split("hourValue", "[-]").alias("split_hours")
).show(50, truncate=False)


Expected Output
---------------

+---------------------------------------------------------------- 
|hourDay  |hourValue  |split_hours   | open_hours   | close_hours
+-----------------------------------------------------------------
|Monday   |9:0-0:0    |[9:0, 0:0]    | [9,0]        | [0,0]       |

person Christine Bui    schedule 19.11.2019    source источник
comment
Не могли бы вы поделиться некоторыми данными и объяснить проблему со всеми входными и выходными данными, которые вы хотите?   -  person Manu Gupta    schedule 20.11.2019
comment
Привет, Ману, результат, который я хотел бы, - это еще один столбец, показывающий [9: 0] с псевдонимом open_hours, и другой с [0: 0] с псевдонимом close_hours, поэтому я могу использовать формулу / выражение для расчета общего количества часов в бизнесе. открыт в неделю   -  person Christine Bui    schedule 20.11.2019
comment
Хорошо, не могли бы вы немного уточнить исходные данные. f.explode(hours).alias(hourDay,hourValue), -> Содержит ли это значение дня и часа. Было бы очень хорошо, если бы вы могли предоставить некоторые исходные образцы данных, чтобы представить ситуацию. 2-3 ряда сделают работу.   -  person Manu Gupta    schedule 21.11.2019
comment
Привет, Ману, это данные из бизнес-данных Yelp, это схема:   -  person Christine Bui    schedule 21.11.2019
comment
Я обновлю исходный пост схемой для данных и скриншотом того, с чем я работаю.   -  person Christine Bui    schedule 21.11.2019
comment
данные о часах просто дают нам часы работы, которые выглядят как [9:0-17:30, 0:0-0:0,,, 9:0-17:30, 9:0-17:30, 9 :0-17:30]   -  person Christine Bui    schedule 21.11.2019
comment
Пожалуйста, проверьте, подойдет ли вам мое решение.   -  person Manu Gupta    schedule 26.11.2019


Ответы (2)


Вот код для этой проблемы. Я искал набор данных Yelp в Интернете и применил к нему решение.

from pyspark.sql import  SparkSession

spark = SparkSession.builder.master("local").appName("Test").getOrCreate()
import pyspark.sql.functions as f
from pyspark.sql.functions import expr,col,when,lit
import json

df1=spark.read.json(r"your_data_path")



df_mon=df1.select("business_id", "name",lit("Monday").alias("hourday"),when(col("hours.Monday").isNotNull(),f.split("hours.Monday",'-')[0]).alias("OpenHours"),when(col("hours.Monday").isNotNull(),f.split("hours.Monday",'-')[1]).alias("CloseHours"))
df_tue=df1.select("business_id", "name",lit("Tuesday").alias("hourday"),when(col("hours.Tuesday").isNotNull(),f.split("hours.Tuesday",'-')[0]).alias("OpenHours"),when(col("hours.Tuesday").isNotNull(),f.split("hours.Tuesday",'-')[1]).alias("CloseHours"))
df_wed=df1.select("business_id", "name",lit("Wednesday").alias("hourday"),when(col("hours.Wednesday").isNotNull(),f.split("hours.Wednesday",'-')[0]).alias("OpenHours"),when(col("hours.Wednesday").isNotNull(),f.split("hours.Wednesday",'-')[1]).alias("CloseHours"))
df_thu=df1.select("business_id", "name",lit("Thursday").alias("hourday"),when(col("hours.Thursday").isNotNull(),f.split("hours.Thursday",'-')[0]).alias("OpenHours"),when(col("hours.Thursday").isNotNull(),f.split("hours.Thursday",'-')[1]).alias("CloseHours"))
df_fri=df1.select("business_id", "name",lit("Friday").alias("hourday"),when(col("hours.Friday").isNotNull(),f.split("hours.Friday",'-')[0]).alias("OpenHours"),when(col("hours.Friday").isNotNull(),f.split("hours.Friday",'-')[1]).alias("CloseHours"))
df_sat=df1.select("business_id", "name",lit("Saturday").alias("hourday"),when(col("hours.Saturday").isNotNull(),f.split("hours.Saturday",'-')[0]).alias("OpenHours"),when(col("hours.Saturday").isNotNull(),f.split("hours.Saturday",'-')[1]).alias("CloseHours"))
df_sun=df1.select("business_id", "name",lit("Sunday").alias("hourday"),when(col("hours.Sunday").isNotNull(),f.split("hours.Sunday",'-')[0]).alias("OpenHours"),when(col("hours.Sunday").isNotNull(),f.split("hours.Sunday",'-')[1]).alias("CloseHours"))

df_final=df_mon.unionAll(df_tue).unionAll(df_wed).unionAll(df_thu).unionAll(df_fri).unionAll(df_sat).unionAll(df_sun)

df_final.show(10,False)

Дайте мне знать, если у вас есть какие-либо вопросы по этому поводу.

person Manu Gupta    schedule 25.11.2019

После вашего вызова pyspark.sql.functions.split вы создадите Column из ArrayType (который также содержит строки). Для доступа к элементам, таким как вложенный столбец, вы должны использовать тот же синтаксис, что и со списками, и даже с фреймами данных Pandas, то есть split(some_column, some_character)[some_index].

Пример:

df = (spark.createDataFrame(
    (("shop", "Monday", "9:0-0:0"),
     ("shop", "Tuesday", "12:30-21:30")),
    schema=("shopname", "day_of_week", "opening_hours")))

from pyspark.sql.functions import split

(df
 .withColumn("opens", split(df.opening_hours, "-")[0])
 .withColumn("closes", split(df.opening_hours, "-")[1])
 .show()
 )

+--------+-----------+-------------+-----+------+
|shopname|day_of_week|opening_hours|opens|closes|
+--------+-----------+-------------+-----+------+
|    shop|     Monday|      9:0-0:0|  9:0|   0:0|
|    shop|    Tuesday|  12:30-21:30|12:30| 21:30|
+--------+-----------+-------------+-----+------+

Обратите внимание, что ваш подход оставит вас с двумя столбцами (последние два, которые я добавил здесь) StringType(). Вы, скорее всего, преобразуете их в числа (например, в минутах с полуночи?), но тогда вам нужно будет изучить возможные минусы, потому что «закрывается в 00:00» на самом деле означает закрытие незадолго до полуночи. Во всяком случае, я оставлю это как вызов.

person Oliver W.    schedule 22.11.2019
comment
Спасибо за помощь! - person Christine Bui; 06.12.2019