1

我正在学习 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)
4

2 回答 2

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   |
+--------------------------------------------+--------+-------+
于 2020-09-21T18:57:01.133 回答
0

您可以通过以下方式做到这一点:

将数据读入数据框。

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)

的

于 2020-09-21T14:06:49.740 回答