Получить различный счет на две агрегации на основе двух разных подмножеств данных с группировкой по - PullRequest
1 голос
/ 02 апреля 2019

Предположим, у меня Dataset<Row> вот так

Day User    isInstall   isPlayed
1   U1      1           1
1   U2      1           0
1   U3      0           1
1   U4      1           0
1   U4      1           1
2   U6      1           1
2   U7      1           0
2   U8      0           1
2   U8      0           1
2   U7      1           0

Я хочу сгруппировать по полю Day и получить количество уникальных пользователей с isInstall равным 1 и isPlayed как 1. Результат должен быть таким:

Day    isInstallUU    isPlayedUU
1      3              3
2      2              2

Я могу получить другой набор данных для счетчиков isInstall & isPlayed, как это, но я запутался, как объединить их и получить один набор данных.

Dataset<Row> result1 = responseDataset.filter(col("isInstall").equalTo(1))
    .groupBy("Day").agg(countDistinct("User").alias("isInstallUU"));

Dataset<Row> result2 = responseDataset.filter(col("isPlayed").equalTo(1))
    .groupBy("Day").agg(countDistinct("User").alias("isPlayedUU"));

Как мне добитьсяэто с помощью API Java Spark?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

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

Самый простой выход - это вычислить два агрегации (как то, что вы пытались) и присоединиться к ним:

Dataset<Row> result1 = responseDataset
    .filter(col("isInstall").equalTo(1))
    .groupBy("Day")
    .agg(countDistinct("User").alias("isInstallUU"));

Dataset<Row> result2 = responseDataset
    .filter(col("isPlayed").equalTo(1))
    .groupBy("Day")
    .agg(countDistinct("User").alias("isPlayedUU"));

Dataset<Row> result = result1
    .join(result2, result1.col("Day").equalTo(result1.col("Day")), "full_outer")
    .na().fill(0);

Обратите внимание, что я использую полное внешнее объединение, потому что могут быть пользователи, которые не отображаются в двух подмножествах.Чтобы избежать нулевых значений, я заменяю их на 0.

EDIT :

Если вам интересно, есть способ сделать это за один этап.Идея состоит в том, чтобы создать 2 дополнительных пользовательских столбца, которые будут нулевыми, когда мы не хотим их агрегировать (искра игнорирует нулевые значения в countDistinct).Это будет выглядеть так:

Dataset<Row> result = responseDataset
    .withColumn("userI", when(col("isInstall").equalTo(1), col("user")))
    .withColumn("userP", when(col("isPlayed").equalTo(1), col("user")))
    .groupBy("day")
    .agg(countDistinct(col("userP")).alias("isPlayedUU"),
         countDistinct(col("userI")).alias("isInstallUU"));
0 голосов
/ 02 апреля 2019

Во-первых, отфильтруйте фрейм данных на основе условий, предоставленных автором.Затем используйте group by для агрегирования по столбцу «Day» и добавьте два новых столбца, которые представляют различные показатели для пользователей.Проверьте ниже код:

    responseDataset.filter(col("isInstall").equalTo(1) && col("isPlayed").equalTo(1))
    .groupBy("Day")
    .agg(countDistinct("User").as("isInstallUU"), countDistinct("User").as("isPlayedUU"));
...