{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Producing and Consuming Messages to/from Kafka and plotting, using python producer and spark consumer\n", "\n", "To run this notebook you must already have created a Kafka topic " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports\n", "\n", "We use utility functions from the hops library to make Kafka configuration simple\n", "\n", "Dependencies: \n", "\n", "- hops-py-util\n", "- confluent-kafka" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Starting Spark application\n" ] }, { "data": { "text/html": [ "
ID | YARN Application ID | Kind | State | Spark UI | Driver log | Current session? |
---|---|---|---|---|---|---|
34 | application_1538483294796_0037 | pyspark | idle | Link | Link | ✔ |
\n", "Sometimes there is a delay before the spark job starts writing to the sink,
\n", "\n", "before going on to the next step in this notebook, go to your HDFS `OUTPUT_PATH` \n", "and verify that the csv output is not empty.
\n", "\n", "If it is empty, re-run the query above
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read the Data from the Sink" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "schema = StructType([\n", " StructField(\"value\", FloatType(), True),\n", " StructField(\"timestamp\", TimestampType(), True)])\n", "\n", "df1 = spark.read \\\n", " .format(\"csv\") \\\n", " .option(\"header\", \"false\") \\\n", " .schema(schema) \\\n", " .load(OUTPUT_PATH)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- value: float (nullable = true)\n", " |-- timestamp: timestamp (nullable = true)" ] } ], "source": [ "df1.printSchema()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize the DataFrame using SparkMagic\n", "\n", "This visualization currenly only works in Python 2.*
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This command copies the spark dataframe from the cluster \n", "to the local machine and converts it to a pandas dataframe named \"df1\". \n", "This pandas dataframe is available in all cells started with the sparkmagic: %%local and can be used for \n", "visualizations and plotting." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "%%spark -o df1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below is sparkmagics default plotting" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "bf3b24a36bee4e8ca5d9ea46c1389c10", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VkJveChjaGlsZHJlbj0oSEJveChjaGlsZHJlbj0oSFRNTCh2YWx1ZT11J1R5cGU6JyksIEJ1dHRvbihkZXNjcmlwdGlvbj11J1RhYmxlJywgbGF5b3V0PUxheW91dCh3aWR0aD11JzcwcHgnKSzigKY=\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "14d51278b25c4bc1b9e631c942bc63dd", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%local\n", "df1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Install matplotlib on the local machine in case it is not already installed" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%bash\n", "pip install --user matplotlib" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "