如何访问数组类型值并在两个不同的列中设置火花?

Posted

技术标签:

【中文标题】如何访问数组类型值并在两个不同的列中设置火花?【英文标题】:How to access array type value and set in two different columns spark? 【发布时间】:2020-09-21 13:30:59 【问题描述】:

我正在学习 Spark,我有下面的 xml,我想从中读取 2 个值并创建两个不同的列

<appRoot>
    <applist>
      <app type="test">
        <code>8.52544</code>
      </app>
      <app type="dev">
        <code>8.52537</code>
      </app>
    </applist>
</appRoot>

我想要

如果 type="test" 那么它应该在新列“app_test”中设置值(即 8.52544)和

如果 type="dev" 那么它应该在新列 "app_dev" 中设置值(即 8.52537)

我在下面尝试过

df.select(
functions.when($"applist.app._type" === "test", $"applist.app.code").as("app_test"),
functions.when($"applist.app._type" === "dev", $"applist.app.code").as("app_dev"))

但它会返回

app_test with value [8.52544, 8.52537]
app_dev with value [8.52544, 8.52537]

在为列设置值时如何区分?

更新:

val df = spark.read
      .format("com.databricks.spark.xml")
      .option("rootTag", "appRoot")
      .option("rowTag", "applist")
      .load("test.xml")

    df.printSchema()



root
 |-- app: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- _type: string (nullable = true)
 |    |    |-- code: double (nullable = true)

【问题讨论】:

@vaquarkhan 仅供参考,我没有否决你的答案,如果你检查我的第一个问题版本,它总是从数组类型列中获取值到两个单独的列中。 我很高兴你得到你的答案:) 【参考方案1】:

使用map_from_entries 可以将数组转换为使用_type 作为键和code 作为值的映射。然后可以使用地图创建两个新列。

val df = spark.read.format("com.databricks.spark.xml")
   .option("rootTag", "appRoot").option("rowTag","applist")
   .load(...)

df.withColumn("map", map_from_entries('app))
   .withColumn("app_test", 'map("test"))
   .withColumn("app_dev", 'map("dev"))
   .drop('map)
   .show(false)

打印(带有一些额外的测试数据)

+--------------------------------------------+--------+-------+
|app                                         |app_test|app_dev|
+--------------------------------------------+--------+-------+
|[[test, 8.52544], [dev, 8.52537], [x, 1.23]]|8.52544 |8.52537|
|[[test, 1.2], [dev, 3.4], [X, 9.9]]         |1.2     |3.4    |
|[[dev, -5.6], [Z, -12.9]]                   |null    |-5.6   |
+--------------------------------------------+--------+-------+

【讨论】:

您在 rootTag 和 rowTag 中指定了什么来读取 XML?由于将 rowTag 指定为 applist,即使 xml 包含多个应用程序标签,也只会获得单行输入。 @ShreyJakhmola 我已经添加了加载 xml 的代码。在我的示例 xml 文件 here 中,我添加了多个 applist 条目以生成额外的行。但是,如果您不需要这些额外的行,您可以节省地忽略它们【参考方案2】:

您可以这样做:

将数据读入数据框。

val df = spark.read.format("com.databricks.spark.xml").option("rootTag", "appRoot").option("rowTag","applist").load("/home/shrey/Downloads/mydoc.xml")
df.printSchema()
df.show()

最后可以通过爆炸数组的方式在when条件中选择合适的列:

df.select(explode($"app").as("app")).select(functions.when($"app._type" === "test", $"app.code").as("app_test"),functions.when($"app._type" === "dev", $"app.code").as("app_dev")).show(false)

如果你想在一行中输出,你可以使用 max() 函数来聚合它。

df.select(explode($"app").as("app")).select(functions.when($"app._type" === "test", $"app.code").as("app_test"),functions.when($"app._type" === "dev", $"app.code").as("app_dev")).agg(max($"app_test").as("app_test"),max($"app_dev").as("app_dev")).show(false)

【讨论】:

请检查我更新的 xml,我添加了一个根标签。所需的字段,即“app”是数组类型

以上是关于如何访问数组类型值并在两个不同的列中设置火花?的主要内容,如果未能解决你的问题,请参考以下文章

访问 BOOL 值并从数组中设置表格单元格

如何从 TempTable 中检索值并在局部变量中设置该值

如何从 Access 数据库中获取值并在 C# winforms Devexpress 的 Gridview 中设置?

来自不同数组的不同值并在表中并排附加在一起

按不同数组中设置的属性类型分隔项目

如何匹配两个 DataFrame 中的特定值并在 Python Pandas 中添加额外的列? [复制]