我想在Spark数据框中计算两个变量x
和y
之间的mutual information(MI),如下所示:
scala> df.show()
+---+---+
| x| y|
+---+---+
| 0| DO|
| 1| FR|
| 0| MK|
| 0| FR|
| 0| RU|
| 0| TN|
| 0| TN|
| 0| KW|
| 1| RU|
| 0| JP|
| 0| US|
| 0| CL|
| 0| ES|
| 0| KR|
| 0| US|
| 0| IT|
| 0| SE|
| 0| MX|
| 0| CN|
| 1| EE|
+---+---+
在我的情况下,x
恰好是事件是否发生(x = 1
)与否(x = 0
),而y
是国家/地区代码,但这些变量可以代表什么。要计算x
和y
之间的MI,我希望上述数据框按x, y
对分组,并附加以下三列:
x
y
x, y
在上面的简短示例中,它看起来像
x, y, count_x, count_y, count_xy
0, FR, 17, 2, 1
1, FR, 3, 2, 1
...
然后我只需计算每个x, y
对的互信息项并求它们。
到目前为止,我已经能够按x, y
对进行分组并汇总count(*)
列,但我找不到有效的方法来添加x
和{{1}计数。我目前的解决方案是将DF转换为数组并手动计算出现次数和同现次数。当y
是一个国家/地区时效果很好但是当y
的基数变大时它会永远存在。有关如何以更多 Sparkish 方式进行操作的任何建议吗?
提前致谢!
答案 0 :(得分:2)
我会使用RDD,为每个用例生成一个密钥,按键计数并加入结果。这样我就知道到底是什么阶段。
rdd.cache() // rdd is your data [x,y]
val xCnt:RDD[Int, Int] = rdd.countByKey
val yCnt:RDD[String, Int] = rdd.countByValue
val xyCnt:RDD[(Int,String), Int] = rdd.map((x, y) => ((x,y), x,y)).countByKey
val tmp = xCnt.cartsian(yCnt).map(((x, xCnt),(y, yCnt)) => ((x,y),xCnt,yCnt))
val miReady = tmp.join(xyCnt).map(((x,y), ((xCnt, yCnt), xyCnt)) => ((x,y), xCnt, yCnt, xyCnt))
另一种选择是使用地图分区,只需处理迭代,并在分区之间合并resolute。
答案 1 :(得分:1)
Spark也是新手,但我知道该怎么做。我不知道这是否是完美的解决方案,但我认为分享这不会有害。
我要做的可能是filter()为值1创建一个Dataframe,filter()为值0为第二个Dataframe
你会得到像
这样的东西1st Dataframe
DO 1
DO 1
FR 1
在下一步中,我将分组(y)
所以你会得到第一个Dataframe
DO 1 1
FR 1
作为GroupedData https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/sql/GroupedData.html
这也有一个count()函数,它应该计算每组的行数。不幸的是,我现在没有时间自己尝试这个,但无论如何我想尝试帮助。
编辑:如果这有帮助,请告诉我,否则我会删除答案,以便其他人仍然看看这个!
答案 2 :(得分:0)
最近,我有同样的任务来计算概率,在这里我想基于Spark的窗口聚合函数分享我的解决方案:
// data is your DataFrame with two columns [x,y]
val cooccurrDF: DataFrame = data
.groupBy(col("x"), col("y"))
.count()
.toDF("x", "y", "count-x-y")
val windowX: WindowSpec = Window.partitionBy("x")
val windowY: WindowSpec = Window.partitionBy("y")
val countsDF: DataFrame = cooccurrDF
.withColumn("count-x", sum("count-x-y") over windowX)
.withColumn("count-y", sum("count-x-y") over windowY)
countsDF.show()
首先,您将两列的每个可能组合分组,并使用count来获取同现数。窗口聚合windowX和windowY允许对聚合行求和,因此您将获得列x或y的计数。
+---+---+---------+-------+-------+
| x| y|count-x-y|count-x|count-y|
+---+---+---------+-------+-------+
| 0| MK| 1| 17| 1|
| 0| MX| 1| 17| 1|
| 1| EE| 1| 3| 1|
| 0| CN| 1| 17| 1|
| 1| RU| 1| 3| 2|
| 0| RU| 1| 17| 2|
| 0| CL| 1| 17| 1|
| 0| ES| 1| 17| 1|
| 0| KR| 1| 17| 1|
| 0| US| 2| 17| 2|
| 1| FR| 1| 3| 2|
| 0| FR| 1| 17| 2|
| 0| TN| 2| 17| 2|
| 0| IT| 1| 17| 1|
| 0| SE| 1| 17| 1|
| 0| DO| 1| 17| 1|
| 0| JP| 1| 17| 1|
| 0| KW| 1| 17| 1|
+---+---+---------+-------+-------+