所以我有一些表格的表格数据:
node parent value
c1 p1 2
p1 3
c2 p1 1
c11 c1 1
c12 c1 1
如果有一个由节点和父列表示的树(父节点可能有多少个子节点),并且每个子节点的值总和=父节点的值。 (我的意思是,这应该是正确的但它可能没有,这就是我想要检查的内容)
我想做的事情:
我想检查一下"每个孩子的价值总和=父母的价值"对输入数据中给出的每个父项都成立。
我在Spark中使用Scala实现这个逻辑,所以我想在功能上实现它。
到目前为止我做了什么:
输入是一个csv文件,我从中创建一个数据帧,并执行以下操作,给我,parent =>孩子的名单,这是我知道我需要的信息。
tree = fileDataFrame.select(parent, node).map( x => (x(0), x(1)).groupByKey()
同样我得到了,node =>价值,这也是有用的信息:
values = fileDataFrame.select(node, value).map( x => (x(0), x(1))
我被困在哪里离开这里。我想要添加所有孩子的值(使用reduceByKey即时猜测),但我还没有设置,因为我有父=>孩子的名单,我需要parent =>儿童价值观清单。
我对函数式编程很陌生,所以我的大脑仍然在循环中思考。
实施此检查的好方法是什么? Spark允许以下转换(http://spark.apache.org/docs/latest/programming-guide.html#transformations)
提前致谢,欢迎提出任何建议!
答案 0 :(得分:2)
我不是理解你的问题,但我认为以下方法应该有效。
首先使用以下架构创建数据框
root
|-- node: string (nullable = true)
|-- parent: string (nullable = true)
|-- value: integer (nullable = true)
汇总儿童数据:
val children = df.groupBy($"parent").agg(sum($"value").alias("csum"))
加入原始数据:
df
.select($"node", $"value")
.join(children, df("node") <=> children("parent"))
.select($"node", ($"value" === $"csum").alias("holds"))
与as suggested的GraphX @mattinbits类似的解决方案:
import org.apache.spark._
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD
val nodes: RDD[(VertexId, (String, Int))] = sc.parallelize(Array(
(0L, ("p1", 3)),
(1L, ("c1", 2)),
(2L, ("c2", 1)),
(11L, ("c11", 1)),
(12L, ("c12", 1))
))
val relationships: RDD[Edge[String]] = sc.parallelize(Array(
Edge(1L, 0L, "child"),
Edge(2L, 0L, "child"),
Edge(11L, 1L, "child"),
Edge(12L, 1L, "child")
))
val graph = Graph(nodes, relationships)
graph.aggregateMessages[(Int, Int)](
triplet => triplet.sendToDst(triplet.dstAttr._2, triplet.srcAttr._2),
(a, b) => (a._1, a._2 + b._2)
).map{case (id, (expected, actual)) => expected == actual}.reduce(_ & _)
答案 1 :(得分:1)
尝试:
val nodeParents: RDD[(String, String, Long)] = // ...
val nodes: RDD[(String, Long)] = nodeParents.map { case(n, _, v) => (n, v) }
val parents: RDD[(String, Long)] = nodeParents.filter { case(_, p, _) => p != ""}
.map { case(_, p, v) => (p, v) }
.reduceByKey(_ + _)
val joined: RDD[(String, (Long, Long))] = parents.join(nodes)
对于你的例子:
> nodes: [(c1, 2), (p1, 3), (c2, 1), (c11, 1), (c12, 1)]
> parents: [(c1, 2), (p1, 3)]
> joined: [(c1, (2, 2)), (p1, (3, 3))]