Marco de datos Pyspark con columna XML y múltiples valores dentro: Extraer columnas fuera de ella
Tengo un marco de datos de pyspark donde una columna tiene un XML dentro. Cada XML en una fila parece así, algunos tienen 2 entradas, unos 3 y 4:
Ejemplo de una entrada de fila:
xml version="1.0" encoding="utf-8"?
Tengo que analizar los valores fuera de ella para el objetivo id, nombre y sexo y crear columnas fuera de él.
Dado que un XML puede tener varias entradas, es difícil generar un número fijo de columnas de él. Mi idea era crear una columna para cada uno de estos atributos (medios añadir 3 columnas al marco de datos), donde entonces las listas están dentro.
en este ejemplo expande el marco de datos pyspark con columnas:
gol id | Nombre | sexo |
---|---|---|
[445,2468,4334,15] | [xxxy,qwerzui,foo,fooh] | [F,F,M,F] |
Estaba pensando en un UDF que itera a través de la columna XML y crea las columnas de ella. ¿Qué piensas de esto, tiene sentido hacerlo de esta manera? Para poder analizar más adelante. En realidad no es común tener listas en columnas.
Lo intenté a través de:
import xml.etree.ElementTree as ET
root = ET.fromstring(string)
y con lo siguiente puedo acceder a los valores dentro, pero no soy capaz de ponerlo en una función de udf adecuada para ampliar mi marco de datos de pyspark.
for child in root:
print(child.tag, child.attrib)
for child in root:
print(child.attrib['age'],child.attrib['sex'])
Desafortunadamente, las otras soluciones de la apiloverflow no podrían ayudarme, así que espero una solución para mi problema
Pregunta hecha hace 3 años, 4 meses, 26 días - Por techwizkid
4 Respuestas:
-
Usa xpath. No es necesario utilizar UDF y debe dar un mejor rendimiento.
df2 = df.selectExpr( ["xpath(col, 'goals/goal/@%s') as %s" % (c,c) for c in ['id', 'name', 'sex']] ) df2.show(20,0) +---------------------+--------------------------+------------+ |id |name |sex | +---------------------+--------------------------+------------+ |[445, 2468, 4334, 15]|[xxxy, qwerzui, foo, fooh]|[F, F, M, F]| +---------------------+--------------------------+------------+
Si quieres añadirlas como nuevas columnas, haz
df2 = df.selectExpr('*', *["xpath(col, 'goals/goal/@%s') as %s" % (c,c) for c in ['id', 'name', 'sex']] )
Respondida el Dec 19, 2020 a las 13:47 - por Kairo
Votos positivos: 0 | Votos negativos: 0 -
El siguiente código genera las 3 listas
import xml.etree.ElementTree as ET XML = '''xml version="1.0" encoding="utf-8"?
Producto
[['445', '2468', '4334', '15'], ['xxxy', 'qwerzui', 'foo', 'fooh'], ['F', 'F', 'M', 'F']]
Respondida el Dec 19, 2020 a las 13:53 - por codesculptor3f6e
Votos positivos: 0 | Votos negativos: 0 -
Para lograr esto en PySpark, puedes usar la función
explode()
para transformar las múltiples entradas dentro de la columna XML en filas individuales y luego pivotear las columnas para obtener la estructura deseada. Aquí te muestro un ejemplo de cómo puedes hacerlo:python from pyspark.sql import SparkSession from pyspark.sql.functions import explode, col
Crear una Spark session
spark = SparkSession.builder.appName("XML parsing").getOrCreate()Crear un DataFrame de ejemplo con una columna 'xml_column' que contiene XML
data = [("xml version='1.0' encoding='utf-8'Definir una función para extraer los atributos del XML y convertirlos en una fila
def extract_attributes(row): root = ET.fromstring(row.xml_column) attributes = [] for child in root: attributes.append((child.attrib['id'], child.attrib['name'], child.attrib['sex'])) return attributesRegistrando la función como un UDF
spark.udf.register("extract_attributes", extract_attributes)Aplicar la función a cada fila del DataFrame
df = df.withColumn("attributes", explode(extract_attributes(col(""))))Pivoteando las columnas para obtener la estructura deseada
df = df.selectExpr("attributes[0] as goal_id", "attributes[1] as name", "attributes[2] as sex") df.show()Con este código, puedes extraer los atributos id, nombre y sexo del XML contenido en la columna 'xmlcolumn', expandirlos en filas individuales y luego pivotearlos en las columnas goalid, name y sex.
Espero que esto te ayude a resolver tu problema. ¡Déjame saber si tienes alguna otra pregunta!
Respondida el Dec 20, 2020 a las 13:43 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Uso de un UDF para Analizar Datos XML
Sí, utilizar un UDF (Función Definida por el Usuario) es un enfoque adecuado para analizar los datos XML dentro de una columna de DataFrame y crear columnas adicionales fuera de ella. Aquí tienes un ejemplo de cómo puedes implementar un UDF para lograr esto:
python from pyspark.sql.functions import udf from pyspark.sql.types import StringType, ArrayType, IntegerType, StringType def parse_xml_goals(xml_string): """ UDF para analizar XML y extraer valores de objetivo (id, nombre y sexo) Args: xml_string (str): Cadena XML que contiene los datos de los objetivos Returns: tuple: Tupla de listas que contienen los valores extraídos para id, nombre y sexo """ try: root = ET.fromstring(xml_string) goals = root.findall("./goals/goal") goal_ids = [int(goal.attrib["id"]) for goal in goals] goal_names = [goal.attrib["name"] for goal in goals] goal_sexes = [goal.attrib["sex"] for goal in goals] return (goal_ids, goal_names, goal_sexes) except Exception as e: print(f"Error al analizar XML: {e}") return ([], [], [])
Crear UDF
parse_xml_goals_udf = udf(parse_xml_goals, ArrayType(IntegerType()), ArrayType(StringType()), ArrayType(StringType()))Aplicar UDF al DataFrame
df = df.withColumn("goal_ids", parse_xml_goals_udf("xml_column")) df = df.withColumn("goal_names", parse_xml_goals_udf("xml_column")[1]) df = df.withColumn("goal_sexes", parse_xml_goals_udf("xml_column")[2])Este UDF analizará la cadena XML en cada fila y extraerá los valores de id, nombre y sexo de los elementos del objetivo. A continuación, devolverá estos valores como tuplas de listas. El DataFrame se ampliará con tres columnas nuevas:
goal_ids
,goal_names
ygoal_sexes
, cada una de las cuales contiene una lista de los valores extraídos para cada entrada XML.Nota:
El esquema de las nuevas columnas dependerá del número de entradas XML dentro de cada fila. Si algunas filas tienen más o menos entradas que otras, las columnas tendrán longitudes variables. Ten en cuenta que si hay algún error al analizar el XML en una fila en particular, el UDF devolverá listas vacías para esa fila.
Respondida el Dec 20, 2020 a las 13:52 - por Gemini
Votos positivos: 0 | Votos negativos: 0