как обновить значение вложенного столбца xml в фрейме данных spark scala - PullRequest
1 голос
/ 27 октября 2019

Предположим, у меня есть следующие данные XML:

<students>
    <studentId>110</studentId>
    <info>
        <rollNo>2</rollNo>
        <address>
            <permanent>abc</permanent>
            <temporary>def</temporary>
        </address>
    </info>
    <subjects>
        <subject>
            <name>maths</name>
            <credit>3</credit>
        </subject>
        <subject>
            <name>science</name>
            <credit>2</credit>
        </subject>
    </subjects>
</students>

И его схема:

root
 |-- info: struct (nullable = true)
 |    |-- address: struct (nullable = true)
 |    |    |-- permanent: string (nullable = true)
 |    |    |-- temporary: string (nullable = true)
 |    |-- rollNo: long (nullable = true)
 |-- studentId: long (nullable = true)
 |-- subjects: struct (nullable = true)
 |    |-- subject: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- credit: long (nullable = true)
 |    |    |    |-- name: string (nullable = true)

в качестве корневого тега "students".

Здесь яхотел обновить значение некоторых столбцов.

Я хотел обновить значение столбца "studentId", используя UDF. И я нашел способ:

df = df.withColumn("studentId", updateValue(col("studentId")))

Затем я хотел обновить вложенный столбец, т.е. "info.rollNo". Применение вышеуказанного процесса дало мне еще один новый столбец как "<info.rollNo>updated_value</info.rollNo>". Поискав некоторое время, я нашел способ:

            val colStruct = df.select(col("info" + ".*")).columns
              .filter(_ != "rollNo")
              .map(f => col("info" + "." + f))
            df = df.withColumn("info",
              struct(
                (colStruct :+ updateValue(col("info.rollNo")
                ).as("rollNo")): _*)
            )

Для третьих вложенных столбцов я попробовал вышеупомянутый способ. Но я не мог понять процесс. Здесь вопрос заключается в том, может ли кто-нибудь объяснить мне алгоритм обновления значения вложенных столбцов, уровень вложенности которого может быть 3,4,5 и так далее. Для экземпляра: я хочу обновить следующие поля. "info.address.permanent", который является struct, и "subjects.subject.credit", который является элементом массива "subject"

PS: Если вам известны какие-либо другие способы обновления определенных столбцов, то, пожалуйста, укажите это.

1 Ответ

0 голосов
/ 01 ноября 2019

Я получил ответ. Что касается обновления столбца x вложенных данных с помощью n1, n2, ..., nn вложений и столбцов c в каждом гнезде:

, т.е. давайте обновим столбец => "n1.n2.n3...nn.x"

df = df.withColumn("n1", 
    struct(
        1st nest's columns n1.c except the struct which holds column x,
        //like col("n1.col1"), col("n2.col2"), ...,
        struct(
            2nd nest's columns n2.c except the struct which holds column x,
            ....
                ....
                    ....
                        struct(
                            nth nest's nn.c columns except column x,
                            udfApplied(col("n1.n2...nn.x")).as("x")
                        ).as("nn")
        ).as("n2")
    ))
val udfApplied = udf((value: String) => {
  value + " updated" //update the value here
})

Пример "info.address.permanent":

df = df.withColumn("info",
  struct(
    col("info.rollNo"),
    struct(
      col("info.address.temporary"),
      udfApplied(col("info.address.permanent")).as("permanent")
    ).as("address")
  ))

Пример "subjects.subject.credit": (Для типов массивов все одинаково, но нам нужно создать структуру для каждогоиндекс элемента в массиве)

df = df.withColumn("subjects",
  struct(
    array(
      struct(
        col("subjects.subject.name")(0).as("name"),
        udfApplied(col("subjects.subject.credit")(0)).as("credit")
      ).as("subject"),
      struct(
        col("subjects.subject.name")(1).as("name"),
        udfApplied(col("subjects.subject.credit")(1)).as("credit")
      ).as("subject")
    ).as("subject")
  ))

Надеюсь, это поможет вам всем

...