连接数据集并重命名一列

Posted

技术标签:

【中文标题】连接数据集并重命名一列【英文标题】:Joining datasets and renaming one column 【发布时间】:2019-02-17 19:26:48 【问题描述】:

我知道如何完成它,但我想(或至少我希望)有一种更简单、更少样板的方法来做同样的事情。

场景:

Employee
+-------+---+------------+
|   NAME|AGE|COMPANY_CODE|
+-------+---+------------+
|   John| 41|           1|
|   Mary| 34|           1|
|  Chris| 32|           2|
|Phillip| 22|           2|
|   Tony| 44|           1|
+-------+---+------------+

Company
+----+---------+
|CODE|     NAME|
+----+---------+
|   1|Company-1|
|   2|Company-2|
|   3|Company-3|
+----+---------+

我的目标是通过 employee.company_code 和 company_code 加入两个表,并将employee.name 显示为 NAME,将employee.age 显示为AGE 和 company.name 为 COMPANY_NAME(这是技巧部分)

// company columns
final Column companyCode = companyDataSet.col("CODE");

// employee columns
final Column employeeCompanyCode = employeeDataSet.col("COMPANY_CODE");

Dataset<Row> join = employeeDataSet.join(companyDataSet, employeeCompanyCode.equalTo(companyCode));

join = join.drop(companyCode).drop(employeeCompanyCode);

打印join数据框,现在我们得到:

+-------+---+---------+
|   NAME|AGE|     NAME|
+-------+---+---------+
|   John| 41|Company-1|
|   Mary| 34|Company-1|
|  Chris| 32|Company-2|
|Phillip| 22|Company-2|
|   Tony| 44|Company-1|
+-------+---+---------+

我不能使用 withColumnRenamed 方法 (join.withColumnRenamed("NAME", "COMPANY_NAME"),因为我有两个名为 NAME 的列,并且都将被重命名

我发现这样做的唯一方法是定义我想要显示的所有列,将所有列传递给选择数据集方法,然后根据需要重命名列:

final Column companyName = companyDataSet.col("NAME");
final Column employeeName = employeeDataSet.col("NAME");
final Column employeeAge = employeeDataSet.col("AGE");

join = join.select(employeeName, employeeAge, companyName.alias("COMPANY_NAME"));

+-------+---+------------+
|   NAME|AGE|COMPANY_NAME|
+-------+---+------------+
|   John| 41|   Company-1|
|   Mary| 34|   Company-1|
|  Chris| 32|   Company-2|
|Phillip| 22|   Company-2|
|   Tony| 44|   Company-1|
+-------+---+------------+

在这种特定情况下,定义我想要选择的所有列并不是什么大问题,因为它们只是几列,但想象一下在具有多列列的表中。因为一个悲惨的列重命名而定义很多列太痛苦了。

知道如何避免这种情况吗?

【问题讨论】:

【参考方案1】:

你应该可以做到:

join = join.withColumnRenamed(companyDataSet.col("NAME"), "COMPANY_NAME")

这能解决你的问题吗?

【讨论】:

spark-sql_2.11 - 2.3.2 - withColumnRenamed 方法需要一个字符串(并且只有一个字符串)作为第一个参数。那可悲!也许在新版本中,它有列的重载版本。【参考方案2】:

一种方法是将它们注册为临时表并编写 SQL?

employee.createOrReplaceTempView(emp)
company.createOrReplaceTempView(comp)

spark.sql("select t1.Name as Name, t1.Age as Age, t2.Name as Company_Name
        from 
        emp t1 join comp t2
        on
        t1.id = t2.id")

【讨论】:

正如我所说,我不想键入所有列名只是为了重命名其中一个。【参考方案3】:

我找到了一个简单的解决方案,不像我认为的 dataset.withColumnRenamed 接受 Column 作为第一个参数那样优雅,但它比仅仅因为一个列重命名而包含所有列要好。

在加入employeeDataSet之前,只需从companyDataSet重命名列NAME:

companyDataSet = companyDataSet.withColumnRenamed("NAME", "COMPANY_NAME");

【讨论】:

以上是关于连接数据集并重命名一列的主要内容,如果未能解决你的问题,请参考以下文章

连接/加入/合并两个缺少一列的数据框

在 Pandas 中基于一列保存数据并由另一列命名

如何将此 KNN 代码应用于我的数据集?

组合行 + 连接大型数据集的值(将 SQL 导出转换为多值)

将数据框的一列与另一列匹配,拉入其他列,组合成大数据集

在 for 循环中连接列