Me estoy convirtiendo un código, escrito con Pandas a PySpark. El código tiene un montón de for loops para crear un número variable de columnas en función especificada por el usuario entradas.

Estoy usando Chispa 1.6.x, con el siguiente código de ejemplo:

from pyspark.sql import SQLContext
from pyspark.sql import functions as F
import pandas as pd
import numpy as np

# create a Pandas DataFrame, then convert to Spark DataFrame
test = sqlContext.createDataFrame(pd.DataFrame({'val1': np.arange(1,11)}))

Que me deja con

+----+
|val1|
+----+
|   1|
|   2|
|   3|
|   4|
|   5|
|   6|
|   7|
|   8|
|   9|
|  10|
+----+

I bucle mucho en el código, por ejemplo el siguiente:

for i in np.arange(2,6).tolist():
    test = test.withColumn('val_' + str(i), F.lit(i ** 2) + test.val1)

Que se traduce en:

+----+-----+-----+-----+-----+
|val1|val_2|val_3|val_4|val_5|
+----+-----+-----+-----+-----+
|   1|    5|   10|   17|   26|
|   2|    6|   11|   18|   27|
|   3|    7|   12|   19|   28|
|   4|    8|   13|   20|   29|
|   5|    9|   14|   21|   30|
|   6|   10|   15|   22|   31|
|   7|   11|   16|   23|   32|
|   8|   12|   17|   24|   33|
|   9|   13|   18|   25|   34|
|  10|   14|   19|   26|   35|
+----+-----+-----+-----+-----+

**Pregunta: * * ¿Cómo puedo reescribir la anterior bucle para ser más eficientes?

Me he dado cuenta de que mi código se ejecuta más lento como Chispa pasa mucho tiempo en cada grupo de bucles (incluso en pequeños conjuntos de datos como la de 2GB de entrada de texto).

Gracias

InformationsquelleAutor nevi_me | 2016-10-14

2 Comentarios

  1. 3

    No es una pequeña sobrecarga en reiteradas llamadas de la JVM método, pero de otro modo bucle for solo no debería ser un problema. Usted puede mejorar ligeramente el uso de un solo select:

    df = spark.range(1, 11).toDF("val1")
    
    def make_col(i):
        return (F.pow(F.lit(i), 2) + F.col("val1")).alias("val_{0}".format(i))
    
    spark.range(1, 11).toDF("val1").select("*", *(make_col(i) for i in range(2, 6)))

    También me gustaría evitar el uso de NumPy tipos. Inicialización de NumPy objetos normalmente es más caro en comparación con simple objetos de Python y la Chispa de SQL no soporta NumPy tipos así hay algunas conversiones adicionales requeridos.

  2. -1

    Uno withColumn trabajará en toda la rdd. Así que por lo general no es una buena práctica utilizar el método para cada columna que desee agregar. Hay una manera que le permite trabajar con columnas y sus datos dentro de una función de mapa. Puesto que una función de mapa está haciendo el trabajo aquí, el código para agregar nueva columna y sus datos será realizado en paralelo.

    una. usted puede obtener nuevos valores basados en los cálculos

    b. Añadir estos nuevos valores de la columna principal rdd como a continuación

    val newColumns: Seq[Any] = Seq(newcol1,newcol2)
    Row.fromSeq(row.toSeq.init ++ newColumns)

    Aquí fila, es la referencia de fila en el método de asignación de

    c. Crear nuevo esquema de la siguiente

    val newColumnsStructType = StructType{Seq(new StructField("newcolName1",IntegerType),new StructField("newColName2", IntegerType))

    d. Agregar el viejo esquema

    val newSchema = StructType(mainDataFrame.schema.init ++ newColumnsStructType)

    e. Crear nuevos dataframe con nuevas columnas

    val newDataFrame = sqlContext.createDataFrame(newRDD, newSchema)
    • Gracias, pero la Scala está haciendo un poco difícil de seguir. Entiendo lo que quieres decir aunque sobre withColumn operativo en todo el DataFrame. Simplemente no puedo envolver mi cabeza alrededor de cómo iba a utilizar map para hacer que funcione.
    • Cuando se utiliza el mapa, se realiza una operación en cada fila. Así que lo que hace es, para cada fila,de crear nuevos esquemas de nuevas columnas, preparar los datos para las columnas, a continuación, añade por encima el nuevo esquema para el viejo esquema(puede obtener de dataframe) y, finalmente, crear nuevos dataframe con nuevas columnas. Usted puede pensar en los pasos anteriores en python, si usted está buscando

Dejar respuesta

Please enter your comment!
Please enter your name here