在DF

2016-07-29 150 views
0

计数两次出现和共生我想两个变量xy,我在一个Spark数据帧,看起来像这样与计算mutual information(MI):在DF

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是国家代码,但这些变量可能代表任何事物。为了计算xy之间的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(*)列,但我无法找到一个有效的方式来添加xy计数。我目前的解决方案是将DF转换为数组并手动计算出现次数和共同出现次数。它在y是一个国家时效果很好,但当y的基数变大时需要永久​​使用。任何建议,我怎么能在更多Sparkish方式?

在此先感谢!

回答

1

我会去与RDDs,为每个用例生成一个密钥,按键计数并加入结果。这样我就知道到底是什么阶段。

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)) 

另一种选择是使用地图分区,并简单地工作在迭代和合并跨分区的决议。

1

也是Spark的新手,但我有一个想法该怎么做。我不知道这是否是完美的解决方案,但我认为分享这不会造成伤害。

我会做什么可能是过滤器()的值1来创建一个数据框和过滤器()为0值的第二个数据帧

你会得到这样的事情

1数据帧

DO 1
DO 1
FR 1

在下一步骤i将GROUPBY(Y)

所以,你会得到的第一个数据帧

DO 1 1

FR 1

由于GroupedData https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/sql/GroupedData.html

这也有应每进行计数行的count()函数组。不幸的是,我现在没有时间自己尝试一下,但我仍然想尝试和帮助。

编辑:请让我知道这是否有帮助,否则我会删除答案,让其他人仍然看看这个!

+0

感谢您的回答。这个解决方案是我暂时使用的解决方案,但我不确定它是否会推广到y的基数为3或更大的情况。粗略地说,它包括明确地制作笛卡尔积(同时考虑'y'只能取两个值)。我认为@ z-star提出了一个更全面的答案。 但是,请不要删除您的答案,它仍然有效,可能对其他用户有用,其他用户可能会帮助您改进。 –