SQL Query to Py(spark)

Tengo la siguiente consulta SQL que quiero convertir a pyspark. Quiero tomar dos columnas pp y género y hacer lo siguiente en pyspark

%sql             
SELECT pp
,       SUM(CASE WHEN Gender = 'M'
               THEN 1.0 ELSE 0.0 END) /
        COUNT(1) AS gender_score
,       count(1) AS total
FROM df 
WHERE gender in ('M', 'F')
GROUP BY pp
HAVING count(1) > 100

Lo intenté.

from pyspark.sql.functions import expr 
test_df = df.withColumn("gender_score", expr("CASE WHEN Gender == 'M' THEN  1 WHEN Gender == 'F' THEN  0 ELSE 'other' END AS male_score"))

Pero no sé cómo puedo seleccionar sólo 2 columnas en pyspark y reproducir la consulta SQL antes mencionada para pyspark

Gracias por adelantado

Pregunta hecha hace 3 años, 4 meses, 29 días - Por geekglitcher1735


4 Respuestas:

  • Si quieres una solución de pitón:

    import pyspark.sql.functions as F
    
    def df_func(df, grp):
        test_df = df.filter( 
            F.col('gender').isin(['M','F'])
            ).groupBy(grp).agg(
                F.mean(
                    F.when(F.col('Gender') == F.lit('M'), 1.0).otherwise(0.0)
                ).alias('gender_score'),
                F.count(F.lit(1)).alias('total')
            ).filter('total > 100')
        return test_df
    
    result = df_func(df, 'pp')
    

    Puede utilizar Spark SQL creando una vista temporal de su dataframe:

    df.createOrReplaceTempView('df')
    query = """
    SELECT pp
    ,       SUM(CASE WHEN Gender = 'M'
                   THEN 1.0 ELSE 0.0 END) /
            COUNT(1) AS gender_score
    ,       count(1) AS total
    FROM df 
    WHERE gender in ('M', 'F')
    GROUP BY pp
    HAVING count(1) > 100
    """
    test_df = spark.sql(query)
    

    Respondida el Dec 16, 2020 a las 10:29 - por algorithmadept

    Votos positivos: 0 | Votos negativos: 0

  • El grupoPor funciones agg() toma múltiples expresiones. Así que puedes hacer una expresión suma/conta.

    val df = spark.sql(""" with t1(
    select 10 pp, 'M' gender union all
    select 10 pp, 'F' gender union all
    select 10 pp, 'M' gender union all
    select 40 pp, 'F' gender 
    ) select * from t1
    """)
    
    df.show(false)
    
    +---+------+
    |pp |gender|
    +---+------+
    |10 |M     |
    |10 |F     |
    |10 |M     |
    |40 |F     |
    +---+------+
    
    df.groupBy("pp").agg (
        (sum(expr("CASE WHEN Gender = 'M' THEN  1 ELSE 0 END "))/count(lit(1)) ).alias("gender_score"),
        count(lit(1)).alias("total")
    ).show(false)
    
    +---+------------------+-----+
    |pp |gender_score      |total|
    +---+------------------+-----+
    |40 |0.0               |1    |
    |10 |0.6666666666666666|3    |
    +---+------------------+-----+
    

    Después de eso puede implementar "tener" usando otro filtro.

    Respondida el Dec 16, 2020 a las 10:38 - por techtactician

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr lo que deseas en pyspark, primero necesitas seleccionar las dos columnas pp y gender, luego realizar los cálculos necesarios y finalmente aplicar las condiciones de filtrado y agrupamiento. Aquí te muestro cómo puedes hacerlo:

    python
    from pyspark.sql import SparkSession
    from pyspark.sql.functions import expr
    
    

    Crear la sesión de Spark

    spark = SparkSession.builder.appName("example").getOrCreate()

    Cargar el DataFrame

    df = spark.read.load("path_to_your_data_file")

    Seleccionar las columnas 'pp' y 'gender'

    df_select = df.select("pp", "gender")

    Realizar los cálculos y filtros

    results = df_select.filter("gender in ('M', 'F')") \ .groupBy("pp") \ .agg((sum(expr("CASE WHEN gender = 'M' THEN 1.0 ELSE 0.0 END")) / count("")).alias("gender_score"), count("").alias("total")) \ .filter("total > 100")

    Mostrar los resultados

    results.show()

    En este código, primero se seleccionan las columnas pp y gender. Luego, se aplican los cálculos con agg para obtener gender_score y total de acuerdo a la lógica de la consulta SQL original. Finalmente, se filtran los resultados con la condición total > 100 y se muestran los resultados.

    Asegúrate de ajustar el nombre del archivo de datos en la línea df = spark.read.load("path_to_your_data_file") con la ruta correcta de tus datos.

    Respondida el Dec 17, 2020 a las 10:29 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • python
    from pyspark.sql import functions as F
    
    

    Select only the 'pp' and 'Gender' columns

    selected_df = df.select('pp', 'Gender')

    Calculate the gender score and total count

    gender_score = selected_df.groupBy('pp').agg( F.sum(F.when(F.col('Gender') == 'M', 1.0).otherwise(0.0)) / F.count(F.col('Gender')), F.count(F.col('Gender')).alias('total') )

    Filter the results to only include rows with a total count greater than 100

    filtered_df = gender_score.filter(F.col('total') > 100)

    Select only the 'pp' and 'gender_score' columns from the filtered results

    result_df = filtered_df.select('pp', 'gender_score')

    Respondida el Dec 17, 2020 a las 10:39 - por Gemini

    Votos positivos: 0 | Votos negativos: 0