Cómo hacer buenos ejemplos de marcos de datos Apache Spark reproducibles


He estado pasando una buena cantidad de tiempo leyendo algunas preguntas con las etiquetas pyspark y spark-dataframe y muy a menudo encuentro que los carteles no proporcionan suficiente información para entender realmente su pregunta. Normalmente comento pidiéndoles que publiquen un MCVE pero a veces conseguir que muestren algunos datos de entrada/salida de muestra es como tirar de los dientes. Por ejemplo: ver los comentarios sobre esta pregunta.

Quizás parte del problema es que la gente simplemente no sabe cómo crear fácilmente un MCVE para marcos de datos spark. Creo que sería útil tener una versión spark-dataframe de esta pregunta de pandas como una guía que se pueda vincular.

Entonces, ¿cómo se crea un buen ejemplo reproducible?

Author: desertnaut, 2018-01-24

4 answers

Proporcione pequeños datos de muestra, que se pueden recrear fácilmente.

Como mínimo, los posters deben proporcionar un par de filas y columnas en su dataframe y código que se puedan usar para crearlo fácilmente. Por fácil, me refiero a cortar y pegar. Hágalo lo más pequeño posible para demostrar su problema.


tengo el siguiente dataframe:

+-----+---+-----+----------+
|index|  X|label|      date|
+-----+---+-----+----------+
|    1|  1|    A|2017-01-01|
|    2|  3|    B|2017-01-02|
|    3|  5|    A|2017-01-03|
|    4|  7|    B|2017-01-04|
+-----+---+-----+----------+

que se puede crear con este código:

df = sqlCtx.createDataFrame(
    [
        (1, 1, 'A', '2017-01-01'),
        (2, 3, 'B', '2017-01-02'),
        (3, 5, 'A', '2017-01-03'),
        (4, 7, 'B', '2017-01-04')
    ],
    ('index', 'X', 'label', 'date')
)

Mostrar el salida.

Haga su pregunta específica y muéstrenos su salida deseada.


¿Cómo puedo crear una nueva columna 'is_divisible' que tiene el valor 'yes' si el día de mes de la 'date' además de los 7 días es divisible por el valor en la columna'X', y 'no' de otra manera?

salida Deseada:

+-----+---+-----+----------+------------+
|index|  X|label|      date|is_divisible|
+-----+---+-----+----------+------------+
|    1|  1|    A|2017-01-01|         yes|
|    2|  3|    B|2017-01-02|         yes|
|    3|  5|    A|2017-01-03|         yes|
|    4|  7|    B|2017-01-04|          no|
+-----+---+-----+----------+------------+

Explica cómo obtener tu salida.

Explicar, con gran detalle, cómo se obtiene su salida deseada. Ayuda a mostrar un ejemplo de cálculo.


Por ejemplo, en la fila 1, la X = 1 y la fecha = 2017-01-01. Agregar 7 días hasta la fecha rinde 2017-01-08. El día del mes es 8 y como 8 es divisible por 1, la respuesta es 'sí'.

Del mismo modo, para la última fila X = 7 y la fecha = 2017-01-04. Agregar 7 a la fecha produce 11 como el día del mes. Dado que 11% 7 no es 0, la respuesta es "no".


Compartir su existente codificar.

Muéstranos lo que has hecho o intentado, incluyendo todo* del código incluso si no funciona. Díganos dónde se está quedando atascado y si recibe un error, incluya el mensaje de error.

(*Puede omitir el código para crear el contexto spark, pero debe incluir todas las importaciones.)


Sé cómo agregar una nueva columna que es date más 7 días, pero estoy teniendo problemas para conseguir el día del mes como un entero.

from pyspark.sql import functions as f
df.withColumn("next_week", f.date_add("date", 7))

Incluye versiones, importaciones y usa resaltado de sintaxis


Para los puestos de ajuste de rendimiento, incluya el plan de ejecución


Análisis de la salida de chispa files

  • MaxU proporcionó un código útil en esta respuesta para ayudar a analizar los archivos de salida de Spark en un DataFrame.

Otras notas.

 33
Author: pault,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-02 03:23:14

Ajuste de rendimiento

Si la pregunta está relacionada con el ajuste de rendimiento, incluya la siguiente información.

Plan de ejecución

Es mejor incluir plan de ejecución extendido. En Python:

df.explain(True) 

En Scala:

df.explain(true)

O plan de ejecución ampliado con estadísticas. En Python:

print(df._jdf.queryExecution().stringWithStats())

En Scala:

df.queryExecution.stringWithStats

Modo e información del clúster

  • mode - local, client, `Cluster.
  • Administrador de clústeres (si corresponde) - ninguno (modo local), independiente, YARN, Mesos, Kubernetes.
  • Información básica de configuración (número de núcleos, memoria del ejecutor).

Información de tiempo

slow es relativo, especialmente cuando portas una aplicación no distribuida o esperas una latencia baja. Los tiempos exactos para diferentes tareas y etapas se pueden recuperar desde la interfaz de usuario de Spark (sc.uiWebUrl) jobs o Spark REST UI.

Usar nombres estandarizados para contextos

El uso de nombres establecidos para cada contexto nos permite reproducir rápidamente el problema.

  • sc para SparkContext.
  • sqlContext para SQLContext.
  • spark para SparkSession.

Proporcionar información de tipo (Scala )

La poderosa inferencia de tipos es una de las características más útiles de Scala, pero hace difícil analizar código sacado de contexto. Incluso si el tipo es obvio desde el contexto, es mejor anotar el variable. Prefer

val lines: RDD[String] = sc.textFile("path")
val words: RDD[String] = lines.flatMap(_.split(" "))

Sobre

val lines = sc.textFile("path")
val words = lines.flatMap(_.split(" "))

Las herramientas de uso común pueden ayudarlo:

  • spark-shell / Scala shell

    Use :t

    scala> val rdd = sc.textFile("README.md")
    rdd: org.apache.spark.rdd.RDD[String] = README.md MapPartitionsRDD[1] at textFile at <console>:24
    
    scala> :t rdd
    org.apache.spark.rdd.RDD[String]
    
  • InteliJ Idea

    Use Alt + =

 17
Author: user8371915,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-27 10:41:28

Buena pregunta y respuesta; algunas sugerencias adicionales:

Incluye tu versión de Spark

La chispa todavía está evolucionando, aunque no tan rápidamente como en los días de 1.x. Siempre es (pero especialmente si está utilizando una versión algo más antigua) una buena idea incluir su versión de trabajo. Personalmente, siempre comienzo mis respuestas con:

spark.version
# u'2.2.0'

O

sc.version
# u'2.2.0'

Incluir tu versión de Python, también, nunca es una mala idea.


Incluya todos sus importaciones

Si su pregunta no es estrictamente sobre Spark SQL & dataframes, por ejemplo, si tiene la intención de usar su dataframe en alguna operación de aprendizaje automático, sea explícito sobre sus importaciones - vea esta pregunta, donde las importaciones se agregaron en el OP solo después de un extenso intercambio en los comentarios (ahora eliminados) (y resultó que estas importaciones incorrectas fueron la causa raíz del problema).

¿Por qué es necesario esto? Porque, por ejemplo, este LDA

from pyspark.mllib.clustering import LDA

Es diferente de este LDA:

from pyspark.ml.clustering import LDA

La primera proviene de la antigua API basada en RDD (anteriormente Spark MLlib), mientras que la segunda proviene de la nueva API basada en dataframe (Spark ML).


Incluir resaltado de código

Bien, confieso que esto es subjetivo: creo que las preguntas de PySpark no deben etiquetarse como python por defecto ; la cosa es, python etiqueta da automáticamente el código de resaltado (y creo que esta es una razón principal para aquellos que lo utilizan para PySpark preguntas). De todos modos, si estás de acuerdo, y todavía te gustaría un código bien resaltado, simplemente incluye la directiva markdown relevante:

<!-- language-all: lang-python -->

En algún lugar de tu post, antes de tu primer fragmento de código.

[ACTUALIZACIÓN: He solicitado resaltado de sintaxis automático para pyspark y sparkr etiquetas-votos positivos más bienvenidos]

 11
Author: desertnaut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-29 00:58:25

Esta pequeña función auxiliar podría ayudar a analizar los archivos de salida de Spark en DataFrame:

PySpark:

def read_spark_output(file_path):
    t = spark.read \
             .option("header","true") \
             .option("inferSchema","true") \
             .option("delimiter","|") \
             .option("parserLib","UNIVOCITY") \
             .option("ignoreLeadingWhiteSpace","true") \
             .option("ignoreTrailingWhiteSpace","true") \
             .option("comment","+") \
             .csv("file:///tmp/spark.out")
    # select not-null columns
    return t.select([c for c in t.columns if not c.startswith("_")])

Scala:

// read Spark Output Fixed width table:
def readSparkOutput(filePath: String) : org.apache.spark.sql.DataFrame = {
    val t = spark.read
                 .option("header","true")
                 .option("inferSchema","true")
                 .option("delimiter","|")
                 .option("parserLib","UNIVOCITY")
                 .option("ignoreLeadingWhiteSpace","true")
                 .option("ignoreTrailingWhiteSpace","true")
                 .option("comment","+")
                 .csv(filePath)
    t.select(t.columns.filterNot(_.startsWith("_c")).map(t(_)):_*)
}

Uso:

df = read_spark_output("file:///tmp/spark.out")
 9
Author: MaxU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-26 00:15:47