2015-09-21 34 views
13

使用Spark 1.5.0并给出以下代码,我希望unionAll根据它们的列名称来联合DataFrame。在代码中,我使用了一些FunSuite传递在SparkContext sc这是怎么回事错`星火unionAll``DataFrame`?

object Entities { 

    case class A (a: Int, b: Int) 
    case class B (b: Int, a: Int) 

    val as = Seq(
    A(1,3), 
    A(2,4) 
) 

    val bs = Seq(
    B(5,3), 
    B(6,4) 
) 
} 

class UnsortedTestSuite extends SparkFunSuite { 

    configuredUnitTest("The truth test.") { sc => 
    val sqlContext = new SQLContext(sc) 
    import sqlContext.implicits._ 
    val aDF = sc.parallelize(Entities.as, 4).toDF 
    val bDF = sc.parallelize(Entities.bs, 4).toDF 
    aDF.show() 
    bDF.show() 
    aDF.unionAll(bDF).show 
    } 
} 

输出:

+---+---+ 
| a| b| 
+---+---+ 
| 1| 3| 
| 2| 4| 
+---+---+ 

+---+---+ 
| b| a| 
+---+---+ 
| 5| 3| 
| 6| 4| 
+---+---+ 

+---+---+ 
| a| b| 
+---+---+ 
| 1| 3| 
| 2| 4| 
| 5| 3| 
| 6| 4| 
+---+---+ 

为什么结果包含混合 “b” 和 “一”列,而不是根据列名对齐列?听起来像一个严重错误!?

回答

26

它看起来不像一个错误。你所看到的是标准的SQL行为,每个主要的RDMBS,包括PostgreSQLMySQL,OracleMS SQL表现完全一样。您会发现SQL Fiddle示例与名称链接。

引述PostgreSQL manual

为了计算集,交集或两个查询的差异,这两个查询必须是“联合兼容”的,这意味着它们将返回相同的列数和相应的列具有兼容的数据类型

列名称(不包括集合操作中的第一个表格)被忽略。

此行为直接来自关系代数,其中基本构建块是元组。由于元组是有序的,因此两组元组的联合是等价的(忽略重复处理)到你得到的输出。

如果你想使用的名字相匹配,你可以做这样的事情

import org.apache.spark.sql.DataFrame 
import org.apache.spark.sql.functions.col 

def unionByName(a: DataFrame, b: DataFrame): DataFrame = { 
    val columns = a.columns.toSet.intersect(b.columns.toSet).map(col).toSeq 
    a.select(columns: _*).unionAll(b.select(columns: _*)) 
} 

要检查这两个名字和类型也应该足够,以取代columns

a.dtypes.toSet.intersect(b.dtypes.toSet).map{case (c, _) => col(c)}.toSeq 
+1

Thx!这不是一个真正的问题,至少在我的情况下,列顺序需要改变。尽管如此,将Scala文档中的这些信息有助于避免错误。不过,我会提供一个'unionAllVia ColumnNames'重新排列列,使得它们在1相匹配:1的方式,如果可能的。 –

+0

@MartinSenne其实Scala的Google文档提供了足够的信息来获得在接受的答案所描述的具体行为。也就是说, '这相当于UNION ALL在SQL' – kasur

+0

@MartinSenne您指出行的排序。这应该在文档中提到。 –

0

正如在SPARK-9813中所讨论的那样,只要跨帧的数据类型和列数相同,unionAll操作应该可以工作。请参阅评论以获取更多讨论。

+1

如果列的顺序不同,那么呢? – sau

2

这个问题在spark2.3中得到修复。他们在数据集中添加对unionByName的支持。

https://issues.apache.org/jira/browse/SPARK-21043