Правильные варианты - 2, 4.
Тут есть несколько интересных моментов:
1️⃣Агрегация
Делается через
.agg() - на вход подается функция, которая что-то считает:F.min(), F.max(), F.count(), F.countDistinct(), F.sum(), F.sumDistinct(), F.avg(), F.mean и т.д.Дополнительно в селекте прописывать не нужно:
df.groupBy("department") \
.agg(F.sum("salary"), \
F.avg("salary"))2️⃣На любое поле можно навесить элиасы
df.groupBy("department")
.agg(F.sum("salary").alias("sum_salary"), \
F.avg("salary").alias("avg_salary"))3️⃣ having не существует
После агрегации у нас появляется новое поле, по которому сразу можно фильтровать. Без элиасов поля будут называться как функция(поле)
# равнозначны
.agg(F.count("customer_id").alias("cnt"))
.where("cnt > 5")
.agg(F.count("customer_id"))
.where("count(customer_id) > 5")
4️⃣ where и filter взаимозаменяемы
Внутри можно использовать как стандартный sql в кавычках, так и делать питоновские/скаловские сравнения:
.where("date = '2024-02-08'")
.filter("date = '2024-02-08'")
.where(F.col('date') == '2024-02-08')
.filter(F.col('date') == '2024-02-08')Обратите внимание, что на Scala тройное равно:
.where("date = '2024-02-08'")
.filter("date = '2024-02-08'")
.where(col("date") === "2024-02-08")
.filter(col("date") === "2024-02-08")col - это обертка над колонкой, которая дает доступ к более крутым функциям поверх: alias(), desc(), like(), isNull() и т.д. #spark