es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

PySpark MapType de valores de columna a matriz de nombres de columna.

Tengo un dataframe de roles y los ids de las personas que desempeñan esos roles. En la tabla de abajo, los roles son a,b,c,d y las personas son a3,36,79,38.

Lo que quiero es un mapa de las personas a un arreglo de sus roles, como se muestra a la derecha de la tabla.



+---+----+----+---+---+--------+
|rec| a| b| c| d| ppl | pplmap
+---+----+----+---+---+--------+-------------------------------------
| D| a3| 36| 36| 36|[a3, 36]| [ a3 -> ['a'], 36 -> ['b','c','d'] ]
| E| a3| 79| 79| a3|[a3, 79]| [ a3 -> ['a','d'], 79 -> ['b','c'] ]
| F|null|null| 38| 38| [38]| [ 38 -> ['c','d'] ]
+---+----+----+---+---+--------+

Y, en realidad, lo que realmente quiero es un informe fácil de leer, como:

txt
D
roles de a3: a
roles de 36: b, c, d
E
roles de a3: a, d
roles de 79: b, c
F
roles de 38: c, d

Estoy usando PySpark 3.

¿Alguna sugerencia? ¡Gracias!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para transformar el dataframe dado en un mapa de personas a un array de sus roles, podemos usar la función explode de PySpark para desglosar las columnas en filas y luego agrupar por personas y sus roles respectivos. El dataframe resultante se puede convertir en un diccionario usando la función collectAsMap de PySpark.

    Aquí cómo hacerlo:

    from pyspark.sql.functions import explode, collect_list, col
    
    # Suponiendo que el dataframe ya está cargado como `df`
    
    # Paso 1: Desglosar las columnas en filas
    df = df.selectExpr("rec", "stack(4, 'a', a, 'b', b, 'c', c, 'd', d) as (role, ppl)")
    
    # Paso 2: Agrupar por personas y recopilar sus roles en un array
    pplmap_df = df.groupBy("ppl").agg(collect_list("role").alias("roles"))
    
    # Paso 3: Convertir el dataframe en un diccionario
    pplmap = pplmap_df.rdd.collectAsMap()
    
    # Paso 4: Generar el informe legible
    for rec, row in df.groupBy("rec").agg(collect_list(col("*")).alias("rows")).collect():
        print(rec)
        for r in row["rows"]:
            print("  {} roles: {}".format(r["ppl"], ", ".join(pplmap.get(r["ppl"], []))))
    

    Esto debería mostrar el informe deseado:

    D
      a3 roles: a
      36 roles: b, c, d
    E
      a3 roles: a, d
      79 roles: b, c
    F
      38 roles: c, d
    

Comments are closed.