我有以下数据框:
|-- k1: array (nullable = true)
| |-- element: long (containsNull = true)
|-- k2: string (nullable = true)
|-- k3: array (nullable = true)
| |-- element: long (containsNull = true)
和
|-- k1: long (nullable = true)
|-- k2: string (nullable = true)
|-- k3: long (nullable = true)
请注意,列名称和类型是相同的,只是第一个数据框的k1
和k3
是数组。我想在k2
上加入这两个数据帧,以便第二个数据帧的条目被附加到第一个数据帧中的数组。例如,如果数据帧是
+---------+---+------------+
| k1 |k2 | k3 |
+---------+---+------------+
|[1, 2, 3]|foo| [4, 5, 6]|
|[7, 8, 9]|bar|[10, 11, 12]|
+---------+---+------------+
和
+-----+---+------+
|k1 |k2 |k3 |
+-----+---+------+
| 4|foo| 7|
| 10|bar| 13|
+-----+---+------+
然后连接的结果应该是
+---+-------------+----------------+
|key| click | search |
+---+-------------+----------------+
|foo|[1, 2, 3, 4] | [4, 5, 6, 7] |
|bar|[7, 8, 9, 10]|[10, 11, 12, 13]|
+---+-------------+----------------+
我的第一个方法是进行内连接以获得
+---+---------+------------+-----+------+
|key| click| search|click|search|
+---+---------+------------+-----+------+
|foo|[1, 2, 3]| [4, 5, 6]| 3| 6|
|bar|[7, 8, 9]|[10, 11, 12]| 9| 12|
+---+---------+------------+-----+------+
然后对结果数据框执行foreach以将所需的行条目附加到数组,然后最后删除后两列。但我无法让打字工作为foreach工作。
我在Java 1.6.1中使用Java 8。我是Spark的新手,所以我们非常感谢任何指导。
答案 0 :(得分:2)
使用java有点棘手。
假设两个数据帧都注册为t1,则t2表然后使用udf将两个数组合并。
sql.udf().register("unionArray", (Seq<Long> arr1, Seq<Long> arr2) -> {
List<Long> output =new ArrayList<Long>();
//Convert Seq object to java list and add to output
output.addAll(scala.collection.JavaConversions.asJavaList(arr1));
output.addAll(scala.collection.JavaConversions.asJavaList(arr2));
//Convert java list output scala Seq
return Option.apply(scala.collection.JavaConverters.asScalaIterableConverter(output).asScala().toSeq());
}, DataTypes.createArrayType(DataTypes.LongType));
sql.sql("select t1.k2 as key,unionArray(t1.k1,t2.k1) as click, unionArray(t1.k3,t2.k3) as search from t1 join t2 on t1.k2 = t2.k2").show();
希望这会有所帮助。
答案 1 :(得分:1)
这不是Java中的解决方案,但是使用UDF
添加列的Scala中的以下方法可以作为参考:
val df1 = Seq(
(Seq(1, 2, 3), "foo", Seq(4, 5, 6)),
(Seq(7, 8, 9), "bar", Seq(10, 11, 12))
).toDF("k1", "k2", "k3")
val df2 = Seq(
(4, "foo", 7),
(10, "bar", 13)
).toDF("k1", "k2", "k3")
def appendCol = udf(
(a: Seq[Int], x: Int) => a :+ x
)
val df3 = df1.join( df2, Seq("k2") ).
withColumn( "click", appendCol(df1("k1"), df2("k1")) ).
withColumn( "search", appendCol(df1("k3"), df2("k3")) )
df3.select( col("k2").as("key"), col("click"), col("search") ).show
+---+-------------+----------------+
|key| click| search|
+---+-------------+----------------+
|foo| [1, 2, 3, 4]| [4, 5, 6, 7]|
|bar|[7, 8, 9, 10]|[10, 11, 12, 13]|
+---+-------------+----------------+