考虑我有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"));
如何使用Java Spark API实现此目标?
答案 0 :(得分:0)
首先,根据作者提供的条件过滤数据框。然后,使用分组依据按“天”列进行汇总,并附加两个新列,分别代表用户的不同计数。 检查以下代码:
responseDataset.filter(col("isInstall").equalTo(1) && col("isPlayed").equalTo(1))
.groupBy("Day")
.agg(countDistinct("User").as("isInstallUU"), countDistinct("User").as("isPlayedUU"));
答案 1 :(得分:0)
一枪做起来有些棘手(但可以做一些工作),因为您正在计算数据的两个不同子集上的聚合。
最简单的方法是计算两个聚合(按照您的尝试)并将其合并:
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。
编辑:
如果您好奇的话,有一种方法可以分阶段进行。我们的想法是创建两个其他用户列,当我们不想聚合它们时它们为空(spark忽略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"));