<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Distributed Computing Archives - relataly.com</title>
	<atom:link href="https://www.relataly.com/tag/distributed-computing/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.relataly.com/tag/distributed-computing/</link>
	<description>The Business AI Blog</description>
	<lastBuildDate>Sat, 27 May 2023 10:13:53 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.relataly.com/wp-content/uploads/2023/04/cropped-AI-cat-Icon-White.png</url>
	<title>Distributed Computing Archives - relataly.com</title>
	<link>https://www.relataly.com/tag/distributed-computing/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">175977316</site>	<item>
		<title>Leveraging Distributed Computing for Weather Analytics with PySpark</title>
		<link>https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/</link>
					<comments>https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/#respond</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Sun, 03 Apr 2022 13:49:00 +0000</pubDate>
				<category><![CDATA[Data Visualization]]></category>
		<category><![CDATA[PySpark]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Seaborn]]></category>
		<category><![CDATA[Weather Analytics]]></category>
		<category><![CDATA[Advanced Tutorials]]></category>
		<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[BigData Analytics]]></category>
		<category><![CDATA[Distributed Computing]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=2739</guid>

					<description><![CDATA[<p>Apache Spark is a popular distributed computing framework for Big Data processing and analytics. In this tutorial, we will work hands-on with PySpark, Spark&#8217;s Python-specific interface. We built on the conceptual knowledge gained in a previous tutorial: Introduction to BigData Analytics with Apache Spark, in which we learned about the essential concepts behind Apache Spark ... <a title="Leveraging Distributed Computing for Weather Analytics with PySpark" class="read-more" href="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/" aria-label="Read more about Leveraging Distributed Computing for Weather Analytics with PySpark">Read more</a></p>
<p>The post <a href="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/">Leveraging Distributed Computing for Weather Analytics with PySpark</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Apache Spark is a popular distributed computing framework for Big Data processing and analytics. In this tutorial, we will work hands-on with PySpark, Spark&#8217;s Python-specific interface. We built on the conceptual knowledge gained in a previous tutorial: <a href="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark/6324/" target="_blank" rel="noreferrer noopener"><em>Introduction to BigData Analytics with Apache Spark</em></a>, in which we learned about the essential concepts behind Apache Spark and its distributed architecture. </p>



<p>The PySpark library provides access to Apache Spark APIs and other cool features like SQL, DataFrame, Streaming, Spark Core, and MLlib for machine learning. Several of these features will help us to prepare and analyze a historical dataset gathered by a weather station in Zurich. You will gain an overview of essential PySpark functions for transforming and querying data in a local computing environment.</p>



<p>The rest of this tutorial proceeds as follows: In the first sections, we will ingest, join, clean, and transform the data using a broad set of PySpark&#8217;s DataFrame functions. In addition, we will touch on the topic of user-defined functions to perform custom transformations. Finally, we will analyze and visualize the data using the Seaborn Python library. As part of the analysis, we work with PySpark SQL, which allows us to register datasets as tables and query them using PySpark SQL syntax.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-kadence-image kb-image_a0bd8f-64 size-large is-resized"><img fetchpriority="high" decoding="async" data-attachment-id="6442" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/image-10-13/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/image-10.png" data-orig-size="1474,547" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-10" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/image-10.png" src="https://www.relataly.com/wp-content/uploads/2022/03/image-10-1024x380.png" alt="Do plot on historical weather data from Zurich, created using PySpark and Seaborn" class="kb-img wp-image-6442" width="693" height="257" srcset="https://www.relataly.com/wp-content/uploads/2022/03/image-10.png 1024w, https://www.relataly.com/wp-content/uploads/2022/03/image-10.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/image-10.png 768w, https://www.relataly.com/wp-content/uploads/2022/03/image-10.png 1474w" sizes="(max-width: 693px) 100vw, 693px" /><figcaption>We can use PySpark and Seaborn to create dot plots like the one above. </figcaption></figure>
</div>
</div>



<h2 class="wp-block-heading">What is Weather Analytics?</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Weather analytics is the process of using data and analytics to understand and predict weather patterns and their impacts. This can involve analyzing historical weather data to identify trends and patterns, using mathematical models to simulate and forecast future weather conditions, and using machine learning algorithms to make more accurate predictions. Weather analytics can be used for a wide range of applications, such as predicting the likelihood of severe weather events, improving agricultural planning and decision-making, and managing energy consumption and supply. By providing insights into future weather conditions, weather analytics can help businesses and organizations to make more informed decisions and mitigate the potential impacts of extreme weather.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<p></p>



<h2 class="wp-block-heading" id="h-analyzing-historical-weather-data-using-pyspark">Analyzing Historical Weather Data using PySpark</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Weather and climate data are interesting resources, not only for weather forecasting but also for dozens of other purposes across different industries. A central area is certainly understanding climate change. Data scientists analyze climate data collected from weather stations around the globe to forecast how climate trends and events unfold. Because the amounts of data are often large, climate analytics is a common application area for distributed computing.</p>



<p>This tutorial guides us through a good use case for distributed data processing. We will process and analyze a set of historical weather data collected from a weather station in Zurich. We aim to explore the relations between climate variables such as temperate, wind, snowfall, and precipitation. However, the primary purpose of this tutorial is to familiarize ourselves with the essential functions of PySpark. Some topics covered in this part are:</p>



<ul class="wp-block-list">
<li>reading and writing DataFrames</li>



<li>selecting, renaming, and manipulating columns</li>



<li>filtering, dropping, sorting, and aggregating rows</li>



<li>joining and transforming data</li>



<li>working with UDFs and Spark SQL functions</li>



<li>While we implement these functions, we will also look into what PySpark does under the hood. </li>
</ul>



<p>PySpark can run on a simulated distributed environment on your local machine. So there is no need for expensive hardware.</p>



<p>The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_03b447-31"><a class="kb-button kt-button button kb-btn_7ddab7-1b kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit  kt-btn-has-text-true kt-btn-has-svg-true  wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-tutorials/blob/master/09%20Distributed%20Analytics/300%20Distributed%20Computing%20-%20Analyzing%20Zurich%20Weather%20Data%20using%20PySpark.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn_236915-75 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit  kt-btn-has-text-true kt-btn-has-svg-true  wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full"><img decoding="async" width="514" height="511" data-attachment-id="12434" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/view-of-zurich-spark-machine-learning-python-tutorial/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png" data-orig-size="514,511" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="view-of-zurich-spark-machine-learning-python-tutorial" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png" src="https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png" alt="" class="wp-image-12434" srcset="https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png 514w, https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png 300w, https://www.relataly.com/wp-content/uploads/2023/02/view-of-zurich-spark-machine-learning-python-tutorial.png 140w" sizes="(max-width: 514px) 100vw, 514px" /><figcaption class="wp-element-caption">Zurich weather knows all seasons.</figcaption></figure>
</div>
</div>



<h3 class="wp-block-heading" id="h-prerequisites">Prerequisites</h3>



<p>This tutorial assumes that you have set up your <a href="https://www.python.org/downloads/" target="_blank" rel="noreferrer noopener">Python 3</a> environment. You can follow&nbsp;<a href="https://www.relataly.com/anaconda-python-environment-machine-learning/1663/" target="_blank" rel="noreferrer noopener">this tutorial</a> to prepare your Anaconda environment if you have not set it up yet. I recommend using Anaconda or Visual Studio Code, but any other Python environment will do.</p>



<p>It is also assumed that you have the following packages installed:&nbsp;<em>pandas, <em>matplotlib, and</em><a href="https://seaborn.pydata.org/#" target="_blank" rel="noreferrer noopener"> seaborn</a></em> for visualization. You can install the packages with the console command:&nbsp;<em>pip install &lt;package name&gt;</em>&nbsp;or, if you use the anaconda packet manager,&nbsp;<em>conda install &lt;package name&gt;</em>. In addition, you need to install the PySpark library. </p>



<p><em>pip install &lt;package name&gt;</em> <em>conda </em></p>



<p><em>install &lt;package name&gt;</em>&nbsp;(if you are using the anaconda packet manager)</p>



<h3 class="wp-block-heading" id="h-download-the-weather-data">Download the Weather Data</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>We will train our model with a public weather dataset that contains daily weather information from Zurich, Switzerland. The data was collected at a weather station between 1979-01-01 and 2021-01-01 and has been divided into two sets, &#8220;A&#8221; and &#8220;B.&#8221; After downloading the files, place them under the following directory: <em>root-folder/data/weather/</em></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full"><img decoding="async" width="511" height="482" data-attachment-id="12445" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/weather-analytics-data-machine-learning-python-spark/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/02/weather-analytics-data-machine-learning-python-spark.png" data-orig-size="511,482" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="weather-analytics-data-machine-learning-python-spark" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/02/weather-analytics-data-machine-learning-python-spark.png" src="https://www.relataly.com/wp-content/uploads/2023/02/weather-analytics-data-machine-learning-python-spark.png" alt="" class="wp-image-12445" srcset="https://www.relataly.com/wp-content/uploads/2023/02/weather-analytics-data-machine-learning-python-spark.png 511w, https://www.relataly.com/wp-content/uploads/2023/02/weather-analytics-data-machine-learning-python-spark.png 300w" sizes="(max-width: 511px) 100vw, 511px" /><figcaption class="wp-element-caption">We will work with a set of weather data from Zurich. Image created with <a href="http://www.midjourney.com" target="_blank" rel="noreferrer noopener">Midjourney</a>.</figcaption></figure>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_9a621c-00"><a class="kb-button kt-button button kb-btn_4b1def-4b kt-btn-size-standard kt-btn-width-type-fixed kb-btn-global-inherit  kt-btn-has-text-true kt-btn-has-svg-false  wp-block-button__link wp-block-kadence-singlebtn" href="https://www.relataly.com/wp-content/uploads/2022/03/zurich-weather-part-a.csv" download="" target="_blank" rel="noreferrer noopener"><span class="kt-btn-inner-text">Download File A </span></a></div>



<ul class="wp-block-list">
<li>date in format YYYY-mm-dd</li>



<li>the wind direction in degrees</li>



<li>max snow depth in mm</li>



<li>precipitation in mm/m²</li>



<li>air pressure in hPa</li>



<li>max wind speed in km/h</li>



<li>average wind speed in km/h</li>



<li>daily sunshine in minutes</li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_e65253-c2"><a class="kb-button kt-button button kb-btn_a200bc-4e kt-btn-size-standard kt-btn-width-type-fixed kb-btn-global-inherit  kt-btn-has-text-true kt-btn-has-svg-false  wp-block-button__link wp-block-kadence-singlebtn" href="https://www.relataly.com/wp-content/uploads/2022/03/zurich-weather-part-b.csv" download="" target="_blank" rel="noreferrer noopener"><span class="kt-btn-inner-text">Download File B </span></a></div>



<ul class="wp-block-list">
<li>date string in format YYYY-MM-DD</li>



<li>the minimum temperature in °C</li>



<li>maximum temperature in °C</li>



<li>avergage temperature in °C</li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"></div>
</div>



<h3 class="wp-block-heading">Step #1 Initialize SparkSession</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>The first step of any Spark application is to create a SparkSession. Older versions of Spark were using contexts for accessing Spark&#8217;s different modules. Since Spark 2.0, SparkSession has replaced SparkContext and has become the unified entry point for accessing Spark APIs and communicating with the cluster.</p>



<p>We can create new SparkSessions by using the getOrCreate() method. This method checks if there is an existing&nbsp;<a href="https://spark.apache.org/docs/2.1.0/api/python/pyspark.sql.html?highlight=sparksession#pyspark.sql.SparkSession" target="_blank" rel="noreferrer noopener">SparkSession</a>, and if it does not find a current Session, the process creates a new instance. Since we are working with a local PySpark installation, this will make a new SparkSession. If you have a SparkCluster available, you can use this cluster by providing the function with the cluster address.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full is-resized"><img decoding="async" data-attachment-id="6431" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/picture1/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/Picture1.jpg" data-orig-size="611,360" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Picture1" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/Picture1.jpg" src="https://www.relataly.com/wp-content/uploads/2022/03/Picture1.jpg" alt="PySpark is the Python-specific interface of Apache Spark" class="wp-image-6431" width="240" height="142" srcset="https://www.relataly.com/wp-content/uploads/2022/03/Picture1.jpg 611w, https://www.relataly.com/wp-content/uploads/2022/03/Picture1.jpg 300w" sizes="(max-width: 240px) 100vw, 240px" /><figcaption class="wp-element-caption">PySpark is the Python-specific interface of Apache Spark</figcaption></figure>
</div>
</div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># A tutorial for this file is available at www.relataly.com

# Import SparkSession from pyspark.sql
from pyspark.sql import SparkSession
from pyspark.sql.types import StringType
from pyspark.sql.functions import col, isnan, when, count, udf, year, month, to_date, mean
import pyspark.sql.functions as F
import seaborn as sns
import matplotlib.pyplot as plt

# Create my_spark
spark = SparkSession.builder.getOrCreate()
print(spark)</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">&lt;pyspark.sql.session.SparkSession object at 0x000001F8C0D10B20&gt;</pre></div>



<h3 class="wp-block-heading">Step #2 Load the Data to a Spark DataFrame</h3>



<p>Next, we want to load two CSV files by invoking the PySpark read function from the SparkSession instance. The function returns a Spark DataFrame, an abstraction layer for interacting with tabular data. </p>



<h4 class="wp-block-heading">2.1 Reading File A</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p>Let&#8217;s read the first file by invoking the read method on the dataframe. Spark will evaluate the read function lazily when we run the read function in the code below. So the read operation does not trigger computation and waits until we call an action. </p>



<p>After running the printSchema method in the code below, the Spark engine performs the &#8220;read&#8221; operation and shows us the result. We would not see any computations if we only used the read function (a transformation) and not any actions. However, we also call summary() to compute some basic statistics on the DataFrame. These action methods trigger Spark to read the data and create a new RDD that contains the data.</p>



<p>Spark supports many formats for reading data, including CSV, JSON, Delta, Parquet, TXT, AVRO, etc. Our data files are in CSV format, separated by a comma. Therefore, we use the .csv function. The code below reads a CSV file into a Spark DataFrame.</p>



<figure class="wp-block-table is-style-regular"><table><thead><tr><th>DataFrame Action</th><th>Description</th></tr></thead><tbody><tr><td>show()</td><td>Displays the top n rows of a DataFrame</td></tr><tr><td>count()</td><td>Counts the number of rows in a DataFrame</td></tr><tr><td>collect()</td><td>Collects the data from the worker nodes and returns them in an array</td></tr><tr><td>summary(), describe()</td><td>Show statistics for string and numeric columns</td></tr><tr><td>first(), head()</td><td>Returns the first row, or several first rows</td></tr><tr><td>take()</td><td>Collects the n first rows and returns them in an array</td></tr></tbody></table><figcaption class="wp-element-caption">Actions Methods on the Spark DataFrame API</figcaption></figure>
</div>
</div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Read File A
spark_weather_df_a = spark.read \
    .option(&quot;header&quot;, False) \
    .option(&quot;sep&quot;, &quot;,&quot;) \
    .option(&quot;inferSchema&quot;, True) \
    .csv(path=f'data/weather/zurich_weather_a')
    
spark_weather_df_a.printSchema()
spark_weather_df_a.describe().show()</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">root
 |-- _c0: integer (nullable = true)
 |-- _c1: string (nullable = true)
 |-- _c2: double (nullable = true)
 |-- _c3: double (nullable = true)
 |-- _c4: double (nullable = true)
 |-- _c5: double (nullable = true)
 |-- _c6: double (nullable = true)
 |-- _c7: double (nullable = true)
 |-- _c8: double (nullable = true)
 |-- _c9: string (nullable = true)

+-------+------------------+----------+-----------------+------------------+-----------------+-----------------+------------------+------------------+------------------+----+
|summary|               _c0|       _c1|              _c2|               _c3|              _c4|              _c5|               _c6|               _c7|               _c8| _c9|
+-------+------------------+----------+-----------------+------------------+-----------------+-----------------+------------------+------------------+------------------+----+
|  count|             15384|     15384|            15363|             15384|            15243|              885|               897|               897|               897|   0|
|   mean|182.61966978679146|      null|9.552613421857709|3.0395995839833567|7.952896411467559|156.8146892655367| 7.334894091415833|27.502229654403596|1017.9076923076926|null|
| stddev|105.74046684963878|      null|7.476849234845438| 6.527361918363559|31.45995738637225|96.54941299923699|4.8985850971655704|16.091181159085917| 8.236341299054192|null|
|    min|                 0|1979-01-01|            -18.0|               0.0|              0.0|              0.0|               2.2|               7.4|             984.7|null|
|    max|               366|2021-01-01|             28.0|              97.8|            550.0|            358.0|              40.4|             113.0|            1042.8|null|
+-------+------------------+----------+-----------------+------------------+-----------------+-----------------+------------------+------------------+------------------+----+</pre></div>



<figure class="wp-block-image size-large"><img decoding="async" src="https://www.relataly.com/wp-content/uploads/2022/04/image-5-1024x349.png" alt="" class="wp-image-6734"/></figure>



<h4 class="wp-block-heading" id="h-2-2-reading-file-b">2.2 Reading File B</h4>



<p>In the code below, you can see the option for header, separate, and inferShema. We are using Spark&#8217;s schema inference option to read the CSV data. However, we must use this function carefully because inferring schema can affect performance. Spark is more sensitive to data types, and inferring the schema does not always work. When we are unsure how the data looks, it is a better solution to make the data types explicit to Spark. In our case, inferSchema has been tested before to ensure it works.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Read File B
spark_weather_df_b = spark.read \
    .option(&quot;header&quot;, False) \
    .option(&quot;sep&quot;, &quot;,&quot;) \
    .option(&quot;inferSchema&quot;, True) \
    .csv(path=f'data/weather/zurich_weather_b')

spark_weather_df_b.printSchema()
spark_weather_df_b.describe().show()</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">root
 |-- _c0: integer (nullable = true)
 |-- _c1: string (nullable = true)
 |-- _c2: double (nullable = true)
 |-- _c3: double (nullable = true)

+-------+------------------+----------+------------------+-----------------+
|summary|               _c0|       _c1|               _c2|              _c3|
+-------+------------------+----------+------------------+-----------------+
|  count|             15383|     15383|             15374|            15368|
|   mean|182.63121627770917|      null|13.705762976453755| 6.06695731389901|
| stddev|105.73420482794731|      null|  8.83091914731549|6.620985806040894|
|    min|                 0|1979-01-01|             -15.2|            -20.8|
|    max|               366|2021-01-01|              36.0|             22.5|
+-------+------------------+----------+------------------+-----------------+</pre></div>



<h3 class="kt-adv-heading_ab6af5-fa wp-block-kadence-advancedheading" data-kb-block="kb-adv-heading_ab6af5-fa">Step #3 Join the Data</h3>



<p>Next, we will join the data from the two files and merge them into a single Spark DataFrame. Whenever we run a transformation on a DataFrame, whether via the SQL or the DataFrame API, we submit a query over to the query plan of the Spark query execution engine. The execution engine will then optimize and execute the query plan. The result is a new Resilient Distributed Dataset (RDD) with the transformed data. Keep this in mind, and imagine what happens underneath the hood as we proceed.</p>



<p>We now have two files containing specific columns of our weather data. To make sense of the data and prepare them for analytics, we will merge the two files into a single DataFrame. In addition, we perform several transformations to bring the data into shape.</p>



<ul class="wp-block-list">
<li>Join the two datasets using the Join function</li>



<li>Remove some columns that we won&#8217;t need via the drop functions</li>



<li>Define new column names</li>



<li>Select and rename columns using Select() with Alias()</li>
</ul>



<p>First, we drop column_c0 because we will not need it.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Drop unused Columns
spark_weather_df_a = spark_weather_df_a.drop(&quot;_c0&quot;)
spark_weather_df_b = spark_weather_df_b.drop(&quot;_c0&quot;)</pre></div>



<p>There are different ways how we can rename columns in PySpark. The first (A) is withColumnRenamed. It requires a separate function call for each column we want to rename. The second is with a custom function and a dictionary. In this way, we can rename multiple columns at once. </p>



<p>After renaming the columns, we use the join function to merge the two datasets based on the row column.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># method A: rename individual columns
spark_weather_df_b_renamed = spark_weather_df_b.withColumnRenamed(&quot;_c1&quot;, &quot;date&quot;) \
    .withColumnRenamed(&quot;_c2&quot;, &quot;max_temp&quot;) \
    .withColumnRenamed(&quot;_c3&quot;, &quot;min_temp&quot;) 
        
# method B: rename multiple columns at once   
def rename_multiple_columns(df, columns):
    if isinstance(columns, dict):
        return df.select(*[F.col(col_name).alias(columns.get(col_name, col_name)) for col_name in df.columns])
    else:
        raise ValueError(&quot;columns need to be in dict format {'existing_name_a':'new_name_a', 'existing_name_b':'new_name_b'}&quot;)

dict_columns = {&quot;_c1&quot;: &quot;date2&quot;, 
                &quot;_c2&quot;: &quot;avg_temp&quot;, 
                &quot;_c3&quot;: &quot;precip&quot;,
                &quot;_c4&quot;: &quot;snow&quot;,
                &quot;_c5&quot;: &quot;wind_dir&quot;,
                &quot;_c6&quot;: &quot;wind_speed&quot;,
                &quot;_c7&quot;: &quot;wind_power&quot;,
                &quot;_c8&quot;: &quot;air_pressure&quot;,
                &quot;_c9&quot;: &quot;sunny_hours&quot;,}
spark_weather_df_a_renamed = rename_multiple_columns(spark_weather_df_a , dict_columns)

# Join the dataframes
spark_weather_df = spark_weather_df_a_renamed.join(spark_weather_df_b_renamed, spark_weather_df_a_renamed.date2 == spark_weather_df_b_renamed.date, &quot;inner&quot;)</pre></div>



<h3 class="wp-block-heading" id="h-step-4-gain-a-quick-overview-of-the-data">Step #4 Gain a Quick Overview of the Data</h3>



<p>When we perform transformations on a new dataset, we typically want to understand the outcome and print out several functions to gain an overview of the data. We can make our lives easier by writing a small function for this purpose, which we can call as needed. Running the custom function below gives us a quick overview of the data. It takes a DataFrame as an argument and performs the following steps:</p>



<ul class="wp-block-list">
<li>Return the two first records </li>



<li>Counting NAN values for all columns that have double or float datatype</li>



<li>Print duplicate values based on the date column. To display the result, we can use the Limit function in combination with the toPandas function</li>



<li>Prints the schema</li>
</ul>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">def quick_overview(df):
   # display the spark dataframe
   print(&quot;FIRST RECORDS&quot;)
   print(df.limit(2).sort(col(&quot;date&quot;), ascending=True).toPandas())

   # count null values
   print(&quot;COUNT NULL VALUES&quot;)
   print(df.select([count(when(isnan(c) | col(c).isNull(), c)).alias(c) for c, y in df.dtypes if y in [&quot;double&quot;, &quot;float&quot;]]
      ).toPandas())

   # print(&quot;DESCRIBE STATISTICS&quot;)
   # print(df.describe().toPandas())
   # # Alternatively to get the max value, we could use max_value = df.agg({&quot;precipitation&quot;: &quot;max&quot;}).collect()[0][0]

   # check for dublicates
   dublicates = df.groupby(spark_weather_df.date) \
    .count() \
    .where('count &gt; 1') \
    .limit(5).toPandas()
   print(dublicates)

   # print schema
   print(&quot;PRINT SCHEMA&quot;)
   print(df.printSchema())

quick_overview(spark_weather_df)</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">FIRST RECORDS
        date2  avg_temp  precip  snow  wind_dir  wind_speed  wind_power  \
0  2020-01-01      -1.8     0.0   0.0      63.0         4.2        14.8   
1  2020-01-01      -1.8     0.0   0.0      63.0         4.2        14.8   

   air_pressure sunny_hours        date  max_temp  min_temp  
0        1034.6        None  2020-01-01      -0.9      -2.9  
1        1034.6        None  2020-01-01      -0.9      -2.9  
COUNT NULL VALUES
   avg_temp  precip  snow  wind_dir  wind_speed  wind_power  air_pressure  \
0        21       0   143     14577       14565       14565         14565   

   max_temp  min_temp  
0         9        15  
         date  count
0  1986-01-01      4
1  2011-01-01      4
2  2005-01-01      4
3  1985-01-01      4
4  2006-01-01      4
PRINT SCHEMA
root
 |-- date2: string (nullable = true)
 |-- avg_temp: double (nullable = true)
 |-- precip: double (nullable = true)
...
 |-- max_temp: double (nullable = true)
 |-- min_temp: double (nullable = true)

None</pre></div>



<p>As we can see, our data has duplicates and missing values. But don&#8217;t worry; we will handle these data quality issues in the next step.</p>



<h3 class="wp-block-heading">Step #5 Clean the Data using Chained Operations</h3>



<p>Spark uses a design pattern that allows us to chain multiple operations. In the next step, we use this feature when we clean and filter the data. On execution, Spark will decide the order in which it performs the transformations as part of an optimized execution plan.</p>



<p>We begin cleaning the data by replacing Null values. Afterward, we will reduce the data size by selecting specific columns in a separate section.</p>



<h4 class="wp-block-heading">5.1 Replacing NA Values with Means</h4>



<p>As we saw in the previous step, there are several NULL values in the temperature and wind columns. Having complete datasets without gaps is preferable when performing historical data analytics. Therefore, we will replace the missing values with the average value. Running the code below, first, calculate the mean values. Subsequently, we use these mean values to replace the Null values. In the second step, we can utilize Spark&#8217;s method-chaining functionality and perform the replace action for several columns in a single line of code. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># calculate mean values
avg = spark_weather_df.filter(spark_weather_df.avg_temp.isNotNull())\
    .select(mean(col('min_temp')).alias('mean_min'), 
            mean(col('max_temp')).alias('mean_max'), 
            mean(col('wind_speed')).alias('mean_wind')).collect()

mean_min = avg[0]['mean_min']
mean_max = avg[0]['mean_max']
mean_wind = avg[0]['mean_wind']

# replace na values with mean values
spark_weather_df = spark_weather_df \
    .na.fill(value=mean_min, subset=[&quot;min_temp&quot;]) \
    .na.fill(value=mean_max, subset=[&quot;max_temp&quot;]) \
    .na.fill(value=mean_wind, subset=[&quot;wind_speed&quot;]) \
    .na.fill(value=0, subset=[&quot;snow&quot;]) 
    
</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">Empty DataFrame Columns: [date, count] Index: []</pre></div>



<h4 class="wp-block-heading">5.2 Removing Duplicates</h4>



<p>We still need to remove duplicate values now that we have a complete dataset. In addition, we will use the following DataFrame methods:</p>



<ul class="wp-block-list">
<li><strong>orderBy</strong>: To sort the data.</li>



<li><b>With column</b>: Select columns and convert data types (to Date type). We can find an overview of the data types supported by PySpark here.</li>



<li><strong>drop</strong>: Used to eliminate individual columns from a dataset.</li>



<li><strong>dropDublicates</strong>: Used to eliminate duplicate records from the dataset.</li>
</ul>



<p>Again, we will use PySpark&#8217;s method chaining feature and invoke all transformations in a single line of code.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># remove dublicates and drop column date2, convert date to datatype &quot;date&quot;, Sort the Data by Date
# drop date2 column, convert date column from string to date type, order by date
spark_cleaned_df = spark_weather_df.dropDuplicates()\
    .drop(col(&quot;date2&quot;))\ # only for demonstration, actually not necessary because we are using select at the end
    .withColumn(&quot;date&quot;, to_date(col(&quot;date&quot;),&quot;yyyy-MM-dd&quot;)) \
    .orderBy(col(&quot;date&quot;)) \
    .select(col(&quot;date&quot;),col(&quot;avg_temp&quot;),col(&quot;min_temp&quot;),col(&quot;max_temp&quot;),col(&quot;wind_speed&quot;),col(&quot;snow&quot;),col(&quot;precip&quot;)) # select columns

quick_overview(spark_cleaned_df)</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">FIRST RECORDS
         date  avg_temp  min_temp  max_temp  wind_speed  snow  precip
0  1979-01-01      -5.3     -12.2      -2.5    7.326082   0.0     1.0
1  1979-01-02     -10.0     -12.2      -4.2    7.326082  10.0     1.7
COUNT NULL VALUES
   avg_temp  min_temp  max_temp  wind_speed  snow  precip
0         0         0         0           0     0       0</pre></div>



<h3 class="wp-block-heading">Step #6 Transform the Data using User Defined Functions (UDFs)</h3>



<p>In addition to the standard methods, PySpark offers the possibility to execute custom Python code in the Spark cluster. Such functions are called User Defined Functions (UDF). When we use UDFs, we should be aware that we won&#8217;t achieve the same performance level as standard PySpark functions.</p>



<p>We want to create several bucks containing several temperature classes in the following. We can use UDFs to create these buckets. However, sometimes we can only achieve a task by using UDFs. By running the code below, we first create a normal Python function called &#8220;binner&#8221; and then hand over this function to a UDF called udf_binner_temp. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># More Infos on User Defined Functions: https://sparkbyexamples.com/pyspark/pyspark-udf-user-defined-function/
# create bucket column for temperature
def binner(min_temp, max_temp):
        if (min_temp is None) or (max_temp is None):
            return &quot;unknown&quot;
        else:
            if min_temp &lt; -10:
                return &quot;freezing cold&quot;
            elif min_temp &lt; -5:
                return &quot;very cold&quot;
            elif min_temp &lt; 0:
                return &quot;cold&quot;
            elif max_temp &lt; 10:
                return &quot;normal&quot;
            elif max_temp &lt; 20:
                return &quot;warm&quot;
            elif max_temp &lt; 30:
                return &quot;hot&quot;
            elif max_temp &gt;= 30:
                return &quot;very hot&quot;
        return &quot;normal&quot;


udf_binner_temp = udf(binner, StringType() )
spark_cleaned_df = spark_cleaned_df.withColumn(&quot;temp_buckets&quot;, udf_binner_temp(col(&quot;min_temp&quot;), col(&quot;max_temp&quot;)))
spark_cleaned_df.limit(10).toPandas()</pre></div>



<p>In the same way, we create buckets to cover different levels of precipitation.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># create new columns for bucket percipitation and for month and year
udf_binner_precip = udf(lambda x: &quot;very rainy&quot; if x &gt; 50 else (&quot;rainy&quot; if x &gt; 0 else &quot;dry&quot;), StringType())
spark_cleaned_df = spark_cleaned_df \
    .withColumn(&quot;precip_buckets&quot;, udf_binner_precip(&quot;precip&quot;)) \
    .withColumn(&quot;month&quot;, month(spark_cleaned_df.date)) \
    .withColumn(&quot;year&quot;, year(spark_cleaned_df.date)) 
spark_cleaned_df.limit(5).toPandas()</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">	date		avg_temp	min_temp	max_temp	wind_speed	snow		precip		temp_buckets
0	1979-01-01	-5.3		-12.2		-2.5		7.326082	0.0			1.0			freezing cold
1	1979-01-02	-10.0		-12.2		-4.2		7.326082	10.0		1.7			freezing cold
2	1979-01-03	-5.8		-7.9		-3.9		7.326082	110.0		0.0			very cold
3	1979-01-04	-8.4		-10.5		-4.4		7.326082	100.0		0.0			freezing cold
4	1979-01-05	-10.0		-11.2		-7.5		7.326082	70.0		0.0			freezing cold
5	1979-01-06	-6.4		-10.1		-2.8		7.326082	50.0		0.0			freezing cold
6	1979-01-07	-3.8		-5.1		-2.9		7.326082	40.0		0.0			very cold
7	1979-01-08	-2.4		-4.5		1.4			7.326082	40.0		5.1			cold
8	1979-01-09	1.4			-0.4		3.8			7.326082	20.0		3.2			cold
9	1979-01-10	0.4			-1.4		2.8			7.326082	10.0		5.4			cold</pre></div>



<p>These steps complete the data preparation. Next, we will focus on analyzing the data.</p>



<h3 class="wp-block-heading">Step #7 Exemplary Data Analysis using Seaborn</h3>



<p>We can analyze the dataset now that we have a clean and consistent set of historical weather data. To aid our analysis, we will visualize the data. Since PySpark does not yet provide its functions for visualization, we will use the Python library Seaborn for visualization.</p>



<p>PySpark provides two different ways to analyze data. The first is standard PySpark methods executed on a DataFrame (sums, counts, average, groupby). The second is PySpark SQL, which allows us to query the data using basic SQL syntax. </p>



<p>The PySpark transformation functions and PySpark SQL are optimized for distributed, parallelized computations on large data sets. In the following, we will explore both ways. This section shows how we can now use the data to create different types of plots:</p>



<ul class="wp-block-list">
<li>Temperature scatterplot with colored dots to highlight historical developments</li>



<li>Heatmap on mean max temperature</li>



<li>Scatterplots that illustrate three-dimensional relationships</li>
</ul>



<h4 class="wp-block-heading">7.1 Temperature Scatterplot with Colored Dots</h4>



<p>In this section, we create a line plot colored by temperature buckets.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># set the dimensions for the scatterplot
fig, ax = plt.subplots(figsize=(28,8))
sns.scatterplot(hue=&quot;temp_buckets&quot;, y=&quot;avg_temp&quot;, x=&quot;date&quot;, data=spark_cleaned_df.toPandas(), palette=&quot;Spectral_r&quot;)

# plot formatting 
ax.tick_params(axis=&quot;x&quot;, rotation=30, labelsize=10, length=0)

# title formatting
mindate = str(spark_cleaned_df.agg({'date': 'min'}).collect()[0]['min(date)'])
maxdate = str(spark_cleaned_df.agg({'date': 'max'}).collect()[0]['max(date)'])
ax.set_title(&quot;average temperature in Zurich: &quot; + mindate + &quot; - &quot; + maxdate)
plt.xlabel(&quot;Year&quot;)
plt.show()</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">	year  	 month   mean(avg_temp)  mean(max_temp)  mean(min_temp)
0  1979      5       19.180000       26.940000       12.900000
1  1979      6       19.200000       25.842857       14.385714
2  1979      7       20.828571       27.071429       15.357143
3  1979      8       20.200000       27.000000       14.216667
4  1979      9       19.000000       25.400000       13.700000</pre></div>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="319" data-attachment-id="11743" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/image-2-3/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/12/image-2.png" data-orig-size="1619,504" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/12/image-2.png" src="https://www.relataly.com/wp-content/uploads/2022/12/image-2-1024x319.png" alt="" class="wp-image-11743" srcset="https://www.relataly.com/wp-content/uploads/2022/12/image-2.png 1024w, https://www.relataly.com/wp-content/uploads/2022/12/image-2.png 300w, https://www.relataly.com/wp-content/uploads/2022/12/image-2.png 768w, https://www.relataly.com/wp-content/uploads/2022/12/image-2.png 1536w, https://www.relataly.com/wp-content/uploads/2022/12/image-2.png 1619w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The outliers to the bottom and top are interesting. While the upward temperature peaks remain relatively stable, the lower temperatures have decreased in the past decades.</p>



<h4 class="wp-block-heading">7.2 Heatmap on Mean Max Temperature</h4>



<p>Next, we want to create a heatmap illustrating how maximum temperature develops over years and months. We first use PySpark to compute the mean of the maximum temperature over years and months. Then we use seaborn to create a heatmap.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">spark_cleaned_df_agg = spark_cleaned_df.select(col(&quot;year&quot;),col(&quot;month&quot;),col(&quot;max_temp&quot;)) \
    .filter(spark_cleaned_df.year &lt; 2021)\
    .groupby(col(&quot;year&quot;),col(&quot;month&quot;))\
    .agg(mean(&quot;max_temp&quot;).alias(&quot;mean_max_temp&quot;)) \
    .orderBy(col(&quot;year&quot;)).toPandas()

plt.figure(figsize=(24,6))
avg_temp_df = spark_cleaned_df_agg.pivot(&quot;month&quot;, &quot;year&quot;, &quot;mean_max_temp&quot;)
sns.heatmap(avg_temp_df, cmap=&quot;Spectral_r&quot;, linewidths=.5)</pre></div>



<figure class="wp-block-image size-large is-resized is-style-default"><img decoding="async" data-attachment-id="6145" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/output-3/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/output-3.png" data-orig-size="1219,371" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="output-3" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/output-3.png" src="https://www.relataly.com/wp-content/uploads/2022/03/output-3-1024x312.png" alt="PySpark big data analytics tutorial - weather heatmap" class="wp-image-6145" width="933" height="284" srcset="https://www.relataly.com/wp-content/uploads/2022/03/output-3.png 1024w, https://www.relataly.com/wp-content/uploads/2022/03/output-3.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/output-3.png 768w, https://www.relataly.com/wp-content/uploads/2022/03/output-3.png 1219w" sizes="(max-width: 933px) 100vw, 933px" /></figure>



<h4 class="wp-block-heading">7.3 Scatterplots</h4>



<p>Next, the goal is to understand the relationship between temperature and weather effects, such as wind or snow. In the following, we will create different scatterplots to display the relationship between other variables. We will show the relationship between min (x-axis) and max temperature (y-axis). In addition, we color the dots to visualize relationships with an additional variable. The code below creates three such scatter plots. The plots display the relationships between the following variables:</p>



<ul class="wp-block-list">
<li>The first plots should illustrate the relationship between temperature and snowfall</li>



<li>We want to demonstrate how wind speed depends on the daily min and max temperature</li>



<li>We want to create a plot that visualizes how daily min and max temperature change over the month</li>
</ul>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">fig, axes= plt.subplots(nrows=1, ncols=3, sharey=True, figsize=(30, 10))
fig.subplots_adjust(hspace=0.5, wspace=0.2)

palette = sns.color_palette(&quot;ch:start=.2,rot=-.3&quot;, as_cmap=True)
sns.scatterplot(ax = axes[0], hue=&quot;snow&quot;, size=&quot;snow&quot;, y=&quot;max_temp&quot;, x=&quot;min_temp&quot;, data=spark_cleaned_df.toPandas(), alpha=1.0, palette=palette)
axes[0].legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0.)
axes[0].set_title(&quot;min - max temperature seperated by snow&quot;)

sns.scatterplot(ax = axes[1], hue=&quot;wind_speed&quot;, size=&quot;wind_speed&quot;, y=&quot;max_temp&quot;, x=&quot;min_temp&quot;, data=spark_cleaned_df.toPandas(), alpha=1.0, palette='rocket_r')
axes[1].legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0.)
axes[1].set_title(&quot;min - max temperature seperated by wind speed&quot;)

sns.scatterplot(ax = axes[2], hue=&quot;month&quot;, y=&quot;max_temp&quot;, x=&quot;min_temp&quot;, data=spark_cleaned_df.toPandas(), alpha=1.0, palette='Spectral_r', hue_norm=(1,12), legend=&quot;full&quot;)
axes[2].legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0.)
axes[2].set_title(&quot;min - max temperature seperated by month&quot;)
</pre></div>



<figure class="wp-block-image size-large is-resized is-style-default"><img decoding="async" data-attachment-id="6101" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/output/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/output.png" data-orig-size="1448,497" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="output" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/output.png" src="https://www.relataly.com/wp-content/uploads/2022/03/output-1024x351.png" alt="PySpark big data analytics tutorial - weather dot plots" class="wp-image-6101" width="941" height="324" srcset="https://www.relataly.com/wp-content/uploads/2022/03/output.png 1024w, https://www.relataly.com/wp-content/uploads/2022/03/output.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/output.png 768w, https://www.relataly.com/wp-content/uploads/2022/03/output.png 1448w" sizes="(max-width: 941px) 100vw, 941px" /></figure>



<p>There are various things we can learn from these plots:</p>



<ol class="wp-block-list">
<li>It is not surprising that most of the snowfall happens at low temperatures. We can also see that most snowfall is around zero degrees Celsius. We also observe some outliers in deep temperature and higher temperature areas. </li>



<li>The highest wind speeds are located in the middle of the plot, where we can also observe the most significant daily difference between the minimum and the maximum temperatures.</li>



<li>The last chart reflects the different seasons. Through the colored areas, we can distinguish the temperature ranges of the individual months.</li>
</ol>



<h3 class="wp-block-heading" id="h-step-8-pyspark-sql">Step #8 PySpark SQL</h3>



<p>PySpark SQL combines classic SQL syntax with distributed computations, which results in increased query performance. Spark SQL is similar to conventional SQL dialects such as MySQL or Microsoft Server. However, Spark provides a dedicated set of functions for everyday data operations such as string transformations, type conversions, etc. The Spark SQL <a href="https://spark.apache.org/docs/latest/sql-ref.html" target="_blank" rel="noreferrer noopener">reference guide</a> offers more information on this topic. </p>



<p>This section aims to extend our analysis by using PySpark SQL. We will display how the daily temperature averages (for minimum, maximum, and mean) have changed. </p>



<p>First, we have to register our dataset as a temporary view. Once we have done that, we can run ad-hoc queries against the View using Spark SQL commands. As you can see, we can use traditional SQL syntax here. The SQL function returns the results in the form of a DataFrame. Running the code below will perform these actions and visualize the results in a line plot.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Data Analysis using PySpark.SQL

# register the dataset as a temp view, so we can use sq
spark_cleaned_df.createOrReplaceTempView(&quot;waeather_data_temp_view&quot;)

# see how event numbers have evolved over years
events_over_years_df = spark.sql( \
        'SELECT year, month, mean(avg_temp), mean(max_temp), mean(min_temp) \
        FROM waeather_data_temp_view \
        WHERE max_temp &gt; 25 \
        GROUP BY month, year \
        ORDER BY year, month')
print(events_over_years_df.limit(5).toPandas())

plt.figure(figsize=(16,6))
fig = sns.lineplot(y=&quot;mean(avg_temp)&quot;, x=&quot;year&quot;, data=events_over_years_df.toPandas(), color= &quot;orange&quot;)
fig = sns.lineplot(y=&quot;mean(max_temp)&quot;, x=&quot;year&quot;, data=events_over_years_df.toPandas(), color= &quot;red&quot;)
fig = sns.lineplot(y=&quot;mean(min_temp)&quot;, x=&quot;year&quot;, data=events_over_years_df.toPandas(), color= &quot;blue&quot;)
plt.grid()
plt.show()
</pre></div>



<figure class="wp-block-image size-full is-resized is-style-default"><img decoding="async" data-attachment-id="6146" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/output-4/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/output-4.png" data-orig-size="951,371" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="output-4" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/output-4.png" src="https://www.relataly.com/wp-content/uploads/2022/03/output-4.png" alt="PySpark big data analytics tutorial 
- Temperature curves created" class="wp-image-6146" width="995" height="388" srcset="https://www.relataly.com/wp-content/uploads/2022/03/output-4.png 951w, https://www.relataly.com/wp-content/uploads/2022/03/output-4.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/output-4.png 768w" sizes="(max-width: 995px) 100vw, 995px" /></figure>



<p>We can express the same Spark query with the DataFrame API. The result is the same.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Using PySpark standard functions
events_over_years_df = spark_cleaned_df\
    .filter(spark_cleaned_df.year &lt; 2021)\
    .groupby(col(&quot;year&quot;))\
    .agg(mean(&quot;avg_temp&quot;).alias(&quot;mean_avg_temp&quot;), 
         mean(&quot;min_temp&quot;).alias(&quot;mean_min_temp&quot;), 
         mean(&quot;max_temp&quot;).alias(&quot;mean_max_temp&quot;))\
    .orderBy(col(&quot;year&quot;)).toPandas()

plt.figure(figsize=(15,6))</pre></div>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>Congratulation, you have made your first steps with distributed computing! This tutorial has demonstrated PySpark &#8211; a distributed computing framework for big data processing and analytics. After initializing the Spark session, we prepared a weather dataset and tested several PySpark functions to process and analyze it. Among the primary data operations were:</p>



<ul class="wp-block-list">
<li>Ingestion of CSV files with the read method</li>



<li>Joining PySpark DataFrames</li>



<li>Cleaning the data by treating duplicates and Null values</li>



<li>Filtering the data and selecting specific columns</li>



<li>Performing custom computations with UDFs</li>



<li>Running analytics and creating plots</li>
</ul>



<p>Although we have used a wide range of functions, we touched only upon the surface of PySpark&#8217;s capabilities. We can do many cool things with PySpark, including real-time data streaming and efficient training of big data machine learning models. We will cover these topics in separate tutorials.</p>



<p>Thanks for reading. I am always happy to receive feedback on my articles. If you have any questions, please let me know in the comments. </p>



<h2 class="wp-block-heading" id="h-sources-and-further-reading">Sources and Further Reading</h2>



<ol class="wp-block-list"><li><a href="https://amzn.to/3gcImKf" target="_blank" rel="noreferrer noopener">Wenig Damji Das and Lee (2020) Learning Spark: Lightning-fast Data Analytics</a></li><li><a href="https://amzn.to/3exFyHb" target="_blank" rel="noreferrer noopener">Chambers and Zaharu (2018) Spark: The Definitive Guide: Big data processing made simple</a></li><li><a href="https://databricks.com/de/wp-content/uploads/2018/12/nsdi_spark.pdf" target="_blank" rel="noreferrer noopener">Resilient Distributed Datasets: A Fault-Tolerant Abstraction for</a></li><li><a href="https://databricks.com/de/wp-content/uploads/2018/12/nsdi_spark.pdf" target="_blank" rel="noreferrer noopener">In-Memory Cluster Computing.pdf</a></li><li><a href="https://amzn.to/3MAy8j5" target="_blank" rel="noreferrer noopener">Andriy Burkov (2020) Machine Learning Engineering</a></li><li><a href="https://amzn.to/3EKidwE" target="_blank" rel="noreferrer noopener">David Forsyth (2019) Applied Machine Learning Springer</a></li></ol>



<p class="has-contrast-2-color has-base-3-background-color has-text-color has-background"><em>The links above to Amazon are affiliate links. By buying through these links, you support the Relataly.com blog and help to cover the hosting costs. Using the links does not affect the price.</em></p>



<p>Articles</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-relataly-com wp-block-embed-relataly-com"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="5mNHJ6qyTd"><a href="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/">Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture&#8221; &#8212; relataly.com" src="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/embed/#?secret=jTuO4a19jc#?secret=5mNHJ6qyTd" data-secret="5mNHJ6qyTd" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>
<p>The post <a href="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/">Leveraging Distributed Computing for Weather Analytics with PySpark</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2739</post-id>	</item>
		<item>
		<title>Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture</title>
		<link>https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/</link>
					<comments>https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/#respond</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Tue, 22 Mar 2022 22:56:52 +0000</pubDate>
				<category><![CDATA[PySpark]]></category>
		<category><![CDATA[Advanced Tutorials]]></category>
		<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[BigData Analytics]]></category>
		<category><![CDATA[Distributed Computing]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=6324</guid>

					<description><![CDATA[<p>Apache Spark is an absolute powerhouse when it comes to open-source Big Data processing and analytics. It&#8217;s used all over the place for everything from data processing to machine learning to real-time stream processing. Thanks to its distributed architecture, it can parallelize workloads like nobody&#8217;s business, making it a lean, mean data processing machine when ... <a title="Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture" class="read-more" href="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/" aria-label="Read more about Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture">Read more</a></p>
<p>The post <a href="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/">Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Apache Spark is an absolute powerhouse when it comes to open-source Big Data processing and analytics. It&#8217;s used all over the place for everything from data processing to machine learning to real-time stream processing. Thanks to its distributed architecture, it can parallelize workloads like nobody&#8217;s business, making it a lean, mean data processing machine when it comes to tackling those truly massive data sets.</p>



<p>So, what&#8217;s the deal with Spark? In this article, we&#8217;re going to give you a rundown of its key concepts and architecture. First things first, we&#8217;ll provide a high-level overview of Spark, including its standout features. We&#8217;ll even throw in a comparison to Apache Hadoop, another popular open-source Big Data processing engine, just for good measure.</p>



<p>From there, we&#8217;ll dive into the nitty-gritty of Spark&#8217;s architecture. You&#8217;ll learn all about how it divides up tasks and data among a cluster of machines, all optimized for top-notch performance when dealing with massive workloads. This is the stuff you need to know to get the most out of Spark, and we&#8217;re going to deliver it straight to you in plain language that anyone can understand.</p>



<p>By the end of this article, you&#8217;ll be well-equipped to get started with Apache Spark, armed with a solid understanding of its core concepts and architecture. You&#8217;ll know exactly how it works and how to use it to process and analyze those gargantuan data sets that would make other Big Data processing engines run for the hills. So let&#8217;s get started and unleash the power of Apache Spark!</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading">What Makes Apache Spark so Successful? </h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Spark has been able to catch a lot of attention in recent years. Due to growing data volumes, more companies are using Apache Spark to handle their steadily increasing data. Companies that use Apache Spark include Amazon, Netflix, Disney, and even NASA. NASA uses Spark to process a data flow of many TB/s that comes from all of their earth monitoring instruments and space observatories around the globe (more on the NASA <a href="https://www.nasa.gov/directorates/heo/scan/services/networks/deep_space_network/about" target="_blank" rel="noreferrer noopener">webpage</a>). Pretty cool, right?</p>



<p>There are various reasons for Spark&#8217;s success. One reason is scalability. Spark has been consistently optimized for parallel computation in scalable distributed systems. Its architecture scales with the workload, thus allowing it to handle different workloads efficiently. This is important as companies want to scale their usage of resources in the cloud depending on use case-specific needs.</p>



<p>Another reason is Spark&#8217;s versatility of use. Spark supports diverse workloads, including batch processing and streaming, machine learning, and SQL analytics. In addition, Spark supports various data types and storage formats, further increasing its versatility and use in different domains. The unique combination of several features and capabilities makes Apache Spark an exciting piece of technology and creates a strong demand for Spark knowledge in the market.</p>



<p>Also: <a href="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/" target="_blank" rel="noreferrer noopener">Leveraging Distributed Computing for Weather Analytics with PySpark</a> </p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full is-resized is-style-default"><img decoding="async" data-attachment-id="5939" data-permalink="https://www.relataly.com/pyspark-distributed-computing-tutorial-analyzing-zurich-weather-data-with-python/2739/image-123/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/11/image.png" data-orig-size="300,168" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/11/image.png" src="https://www.relataly.com/wp-content/uploads/2021/11/image.png" alt="Apache Spark is a powerful library for processing big data in a distributed fashion" class="wp-image-5939" width="252" height="141"/><figcaption class="wp-element-caption">Apache Spark &#8211; one of the best open-source engines for Big Data processing and analysis</figcaption></figure>
</div>
</div>



<h2 class="wp-block-heading">Spark Features</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>Spark was initially launched in 2009 by Matei Zaharia at UC Berkeley&#8217;s AMPLab. It was later released as open-source under a BSD license in 2010. Since 2013, Spark has been part of the Apache Software Foundation, which currently (2022) lists it as a top-priority project. Key features of the Spark ecosystem are:</p>



<ul class="wp-block-list">
<li><strong>In-Memory Processing</strong>: Spark is designed for in-memory computations to avoid writing data to disk and achieve high speed.</li>



<li><strong>Open Source</strong>: The development and promotion of Spark are driven by a growing community of practitioners and researchers.</li>



<li><strong>Reusability:</strong> Spark promotes code reuse through standard functions and method piling. </li>



<li><strong>Fault Tolerance:</strong> Spark comes with built-in fault tolerance, making Spark resilient against outtakes of cluster nodes. </li>



<li><strong>Real-time Streaming:</strong> Spark provides enhanced capabilities for real-time streaming of big data.</li>



<li><strong>Compatibility:</strong> Spark integrates well with existing big-data technologies such as Hadoop and offers support for various programming languages, incl. R, Python, Scala, and Java. </li>



<li><strong>Built-in Optimization:</strong> Spark has a built-in optimization engine. It is based on the lazy evaluation paradigm and uses acyclic-directed graphs (DAG) to create execution plans that optimize transformations.</li>



<li><strong>Analytics-ready:</strong> Spark provides powerful libraries for querying structured data inside Spark, using either SQL or DataFrame API. In addition, Spark comes with ML Flow, an integrated library for machine learning that can execute large ML workloads in memory. </li>
</ul>



<p>Spark combines these features and provides a one-stop-shop solution, thus making it extremely powerful and versatile.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<p>. </p>



<h2 class="wp-block-heading" id="h-local-vs-distributed-computing">Local vs. Distributed Computing</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>To understand how Spark works, it&#8217;s helpful to compare a local system to a distributed computing system. While a local system can handle smaller workloads, it has several limitations when it comes to Big Data processing. </p>



<p>One limitation is the number of cores. Modern CPUs typically have at least two processing cores, but the maximum number of cores in a single machine is around 16 to 32. This means that the number of cores does not scale, which is a problem when working with large data sets.</p>



<p>Another limitation is the amount of RAM that a single computer can handle. While it&#8217;s theoretically possible to increase RAM up to a Terrabyte (TB), this is not cost-efficient. Additionally, running extensive computations on a single machine can be risky, as a single error can require starting the entire job over again.</p>



<p>To overcome these limitations, it makes sense to move toward a distributed architecture. In a distributed system, a network of machines can work on several tasks in parallel. This is where Spark shines, as it is designed to run best on a computing cluster.</p>



<p>By leveraging a distributed architecture, Spark can parallelize workloads and optimize performance to handle massive data sets. With a network of machines working together, Spark can tackle complex computations in a robust and efficient way. In summary, the move to a distributed architecture is critical for overcoming the limitations of a local system and unlocking the full potential of Spark.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="581" data-attachment-id="6725" data-permalink="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/image-4-14/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/04/image-4.png" data-orig-size="1494,847" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-4" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/04/image-4.png" src="https://www.relataly.com/wp-content/uploads/2022/04/image-4-1024x581.png" alt="Local System vs Distributed System, Spark Tutorial" class="wp-image-6725" srcset="https://www.relataly.com/wp-content/uploads/2022/04/image-4.png 1024w, https://www.relataly.com/wp-content/uploads/2022/04/image-4.png 300w, https://www.relataly.com/wp-content/uploads/2022/04/image-4.png 768w, https://www.relataly.com/wp-content/uploads/2022/04/image-4.png 1494w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">A local system, in comparison with a distributed system</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading">Cluster Computations</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>When it comes to Big Data, you want to parallelize as much as possible, as this can significantly reduce the time for processing workloads. If we speak about processing Terrabytes or Petabytes of data, we need to distribute the workload among a whole cluster of computers with hundreds or even thousands of cores. Here we run into another limitation: parallelization requires us to distribute tasks among cluster nodes, split the data, and store smaller chunks of data in each node. </p>



<p>Distributing the data across a cluster means transferring the data to the machines and either writing it to the hard disk or storing it in the Random Access Memory (RAM). Both choices have their pros and cons. While disk space is typically cheap, write operations are generally slow and thus expensive in terms of performance. Keeping the data in memory (RAM) is much faster. However, RAM is typically expensive. Compared to disk, there is less RAM space available to store the data, which requires breaking them up into a more significant number of smaller partitions.</p>



<h2 class="wp-block-heading">Spark vs. Hadoop</h2>



<p>Cluster computing frameworks existed long before Apache Spark. For example, Apache Hadoop was developed long before Apache Spark and used by many enterprises to process large workloads for some time.</p>



<h3 class="wp-block-heading">A Matter of Persistence</h3>



<p>Hadoop distributes the data across the nodes of a computing cluster. It then runs local calculations on the cluster nodes and collects the results. For this purpose, Hadoop relies on MapReduce, which persists the data to a distributed file system. An example is the <a href="https://databricks.com/de/glossary/hadoop-distributed-file-system-hdfs" target="_blank" rel="noreferrer noopener">Hadoop Distributed File System (HDFS)</a>. The advantage is that users don&#8217;t have to worry about task distributions or fault tolerance. Hadoop handles all of this under the hood. </p>



<p>The downside of MapReduce is that reads and writes take place on the local table storage, which is typically slow. However, modern analytics use cases often rely on the swift processing of large data volumes. Or in the case of machine learning and ad-hoc analytics, they require frequent iterative changes to the data. For these use cases, Spark provides a faster solution. Apache spark overcomes the costly persistence of data to the local table storage by keeping it in the RAM of the worker nodes. Spark will only spill data to the disk if the memory is full. Keeping data in memory can improve the performance of large workloads by an order of magnitude. The speed advantage can be as much as 100x.</p>



<h3 class="wp-block-heading">When to Use Spark?</h3>



<p>Spark&#8217;s in-memory approach offers a significant advantage if speed is crucial and the data fits into RAM. Especially when use cases require real-time analytics, Spark offers superior performance over Hadoop MapReduce. Such cases are, for example:</p>



<ul class="wp-block-list">
<li><strong>Credit card fraud detection</strong>: Analysis of large volumes of transactions in real-time.</li>



<li><strong>Predictive Maintenance: </strong>Prediction of sensor data anomalies and potential machine failures with real-time analysis of IoT sensor data from machines and production equipment.</li>
</ul>



<p>However, Spark is not always the best solution. For example, Hadoop may still be a great choice when processing speed is not critical. Sometimes the data may be too big for in-memory storage, even on a large computing cluster. In such cases, using Hadoop on a cluster optimized for this purpose can be more cost-effective. So, there are also cases where Hadoop offers advantages over Spark.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading" id="h-spark-architecture">Spark Architecture</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>The secret to Spark&#8217;s performance is massive parallelization. Parallelization is achieved by decomposing a complex application into smaller jobs executed in parallel. Understanding this process requires looking at the distributed cluster upon which Spark will run its jobs. </p>



<p>A Spark cluster is a collection of virtual machines that allows us to run different workloads, including ETL and machine learning. Each computer typically has its RAM and multiple cores, allowing the system to speed up computations massively. Of course, cluster sizes may vary, but the general architecture remains generic.</p>



<p>A spark computing cluster has a driver node and several worker nodes. The driver node contains a driver program that sends tasks via a cluster manager to the worker nodes. Each worker node has an executer and holds only a fraction of the total data in its cache. </p>



<p>After job completion, the worker nodes send back the results, where the driver program aggregates them. This way, Spark avoids storing the data in the local disk storage and achieves swift execution. </p>



<p>Another advantage of this architecture is easy scaling. In a cluster, you can add machines to the network to increase computational power or remove them again when they are not needed.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"><div class="wp-block-image">
<figure class="alignright size-large is-resized"><img decoding="async" data-attachment-id="6366" data-permalink="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/image-15-11/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/image-15.png" data-orig-size="1445,974" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-15" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/image-15.png" src="https://www.relataly.com/wp-content/uploads/2022/03/image-15-1024x690.png" alt="Interplay between the different components of a Spark computing cluster, Spark Tutorial" class="wp-image-6366" width="417" height="281" srcset="https://www.relataly.com/wp-content/uploads/2022/03/image-15.png 1024w, https://www.relataly.com/wp-content/uploads/2022/03/image-15.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/image-15.png 768w, https://www.relataly.com/wp-content/uploads/2022/03/image-15.png 1445w" sizes="(max-width: 417px) 100vw, 417px" /><figcaption class="wp-element-caption">The interplay between the different components of a Spark computing cluster<br>Source: based on https://spark.apache.org/docs/latest/cluster-overview.html</figcaption></figure>
</div></div>
</div>



<h3 class="wp-block-heading">Spark Cluster Components</h3>



<p>Clusters consist of a single driver node, multiple worker nodes, and several other key components:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h4 class="wp-block-heading">Driver Node</h4>



<p>The driver node has the role of an orchestrator in the computing cluster. It runs a java process that decomposes complex transformations (transformation and action) into the smallest units of work called tasks. It distributes them to the worker nodes for parallel execution as part of an execution plan (more on this topic later). </p>



<p>The driver program also launches the workers who read the input data from a distributed file system, decompose it into smaller partitions, and persist them in memory.</p>



<p>Spark has been designed to optimize task planning and execution automatically. In addition, the driver creates the Spark context (and Spark Session) that provides access to and deployment of cluster information, functions, and configurations.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h4 class="wp-block-heading">Worker Node</h4>



<p>Worker nodes are the entities that get the actual work done. Each worker hosts an executor on which the individual tasks run. Workers have a fixed number of executors that contain free slots for several tasks. </p>



<p>Workers also have their dedicated cache memory to store the data during processing. However, when the data is too big to store in memory, the executor will spill it onto the disk. The number of slots and ram available to store the data depends on the cluster configuration and its underlying hardware setup.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h4 class="wp-block-heading">Cluster Manager</h4>



<p>A cluster manager is the core process in Spark responsible for launching executors and managing the optimal distribution of tasks and data across a distributed computation cluster. </p>



<p>Spark supports different disk storage formats, including HDSF and Cassandra. The storage format is essential because it describes how Spark distributes the data across a network. For example, HDFS partitions the data into blocks of 128 MB and replicates these blocks three times &#8211; in this way, creating duplicate data to achieve fault tolerance. The fact that Spark can handle different storage formats makes it very flexible.</p>
</div>
</div>



<h4 class="wp-block-heading" id="h-executor">Executor</h4>



<p>The executors are processes launched in coordination with the cluster manager. Once the executor is launched, it runs as long as the Spark application runs. They are responsible for executing tasks and returning the results to the driver. Each executor holds a fraction (a Spark Partition) of the data to be processed. The executor persists the data in the cache memory of the worker node unless the cache is full. </p>



<h2 class="wp-block-heading">The Resilient Distributed Dataset (RDD) </h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p>The backbone of Apache Spark is the Resilient Distributed Dataset (RDD). The RDD is a distributed memory abstraction that provides functions for in-memory computations on large computing clusters. </p>



<p>Imagine you want to carry out a transformation on a set of historical temperature data. Running this on Spark will create an RDD. The RDD partitions the data and distributes the partitions to different worker nodes in the cluster.</p>



<p>The RDD has four main features:</p>



<ul class="wp-block-list">
<li><strong>Partitioning</strong>: An RDD is a distributed collection of data elements partitioned across nodes in a cluster. Partitions are sets of records stored on one physical machine in the cluster.</li>



<li><strong>Resilience:</strong> RDDs achieve fault tolerance against failures of individual nodes through redundant data replication. </li>



<li><strong>Interface</strong>: The RDD provides a low-level API that allows performing transformations and tasks parallel to the data.</li>



<li><strong>Immutability:</strong> An RDD is an immutable replication of data, which means that changing the data requires creating a new RDD. </li>
</ul>



<p>Since Spark 2.0, the Spark syntax orients towards the DataFrame object. As a result, you won&#8217;t interact with the RDD object anymore when writing code. However, the RDD is still how Spark stores data in memory and the RDD continues to excel under the hood.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"><div class="wp-block-image">
<figure class="alignright size-large is-resized"><img decoding="async" data-attachment-id="6722" data-permalink="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/image-3/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/04/image-3.png" data-orig-size="1773,1440" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-3" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/04/image-3.png" src="https://www.relataly.com/wp-content/uploads/2022/04/image-3-1024x832.png" alt="Distribution of Partitioned Data across a Spark Cluster with RDD, Apache Spark Tutorial" class="wp-image-6722" width="413" height="335" srcset="https://www.relataly.com/wp-content/uploads/2022/04/image-3.png 1024w, https://www.relataly.com/wp-content/uploads/2022/04/image-3.png 300w, https://www.relataly.com/wp-content/uploads/2022/04/image-3.png 768w, https://www.relataly.com/wp-content/uploads/2022/04/image-3.png 1536w, https://www.relataly.com/wp-content/uploads/2022/04/image-3.png 1773w" sizes="(max-width: 413px) 100vw, 413px" /><figcaption class="wp-element-caption">Partitioning and distributing data across nodes in the process of creating an RDD</figcaption></figure>
</div></div>
</div>



<h3 class="wp-block-heading">Performance Optimization</h3>



<p>Processing data in distributed systems leads to an increased need for optimization. Spark already takes care of several optimizations, and new Spark versions constantly get better at improving performance. However, there are still cases where it is necessary to finetune things manually. </p>



<p>Essential concepts that allow Spark to distribute the computation cluster&#8217;s work efficiently are &#8220;lazy code evaluation&#8221; and &#8220;data shuffling.&#8221; </p>



<h3 class="wp-block-heading">Lazy Code Evaluation</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p>An essential pillar of Spark is the so-called lazy evaluation of transformations. The underlying premise is that Spark does not directly modify the data but only when the user calls an action. </p>



<p>Examples of transformations are join, select, groupBy, or partitionBy. When the user calls an &#8220;action,&#8221; the execution of transformations creates a new RDD. In contrast, actions collect results from the worker nodes and return them to the driver node. Examples of actions are &#8220;first,&#8221; &#8220;max&#8221;, &#8220;count&#8221;, or &#8220;collect&#8221;. For a complete list of transformations and actions, visit the Spark website.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">sparkDF.withColumn('split_text', F.explode(F.split(F.lower('Word'), ''))) \
         .filter(&quot;split_text != ''&quot;) \
         .groupBy(&quot;split_text&quot;, &quot;language&quot;)\
         .pivot(&quot;split_text&quot;) \
         .agg(count(&quot;split_text&quot;)
     ).drop(&quot;Word_new&quot;, &quot;Word&quot;, &quot;split_text&quot;).orderBy([&quot;language&quot;], ascending=[0, 0]).na.fill(0)
</pre></div>
</div>
</div>



<p>Spark can look at all transformations from a holistic perspective by lazily evaluating the code and carrying out optimizations. Before executing the transformation, Spark will generate an execution plan that considers all the operations and beneficially arranges them. </p>



<p>It is worth mentioning that Spark supports methods piling so that programmers can group multiple transformations without worrying about their order. The code example on the right illustrates this approach for the Python-specific API of Spark called PySpark.</p>



<h3 class="wp-block-heading">Shuffle Operations</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p>Shuffle is a technique for re-distributing data in a computation cluster. After a shuffle operation, the partitions are grouped differently among the cluster nodes. The illustration demonstrates this procedure. </p>



<h4 class="wp-block-heading">An Expensive Operation</h4>



<p>Shuffle typically requires copying data between executors and machines, thus making it an expensive operation. It requires data transfer between worker nodes, resulting in disk I/O and network-I/O. For this reason, we should avoid shuffle operations, if possible. However, several common transformations will invoke shuffle. Examples are join-operations, repartition-operations, and groupBy-operations. These operations will not work without shuffling the data because they often require a complete dataset. </p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"><div class="wp-block-image">
<figure class="alignright size-large is-resized"><img decoding="async" data-attachment-id="6720" data-permalink="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/image-2-2/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/04/image-2.png" data-orig-size="1092,924" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/04/image-2.png" src="https://www.relataly.com/wp-content/uploads/2022/04/image-2-1024x866.png" alt="Spark Shuffle Operation Between Two Worker Nodes, Apache Spark Tutorial" class="wp-image-6720" width="407" height="344" srcset="https://www.relataly.com/wp-content/uploads/2022/04/image-2.png 1024w, https://www.relataly.com/wp-content/uploads/2022/04/image-2.png 300w, https://www.relataly.com/wp-content/uploads/2022/04/image-2.png 768w, https://www.relataly.com/wp-content/uploads/2022/04/image-2.png 1092w" sizes="(max-width: 407px) 100vw, 407px" /><figcaption class="wp-element-caption">Spark shuffle operation between two worker nodes</figcaption></figure>
</div></div>
</div>



<h4 class="wp-block-heading">Avoiding Shuffle</h4>



<p>Spark has several built-in features that help Spark avoid shuffling. However, some of these activities, such as scanning large datasets, will also cost performance. If the user already knows the scope and structure of the data, they should provide this information directly to Spark. Spark offers various parameters in its APIs for this purpose.</p>



<p>Avoiding shuffle operations may require manual optimization. A typical example is working with data sets that differ significantly in size (skewed data). For example, when doing join operations between a large and a small dataset, we can avoid shuffle operations by providing each worker node with a full copy of the smaller dataset. For this purpose, Spark has a broadcast function. The broadcast function copies a dataset to all worker nodes in the cluster, reducing the need to exchange partitions between nodes.</p>



<p>There are many more topics around optimizations. But since it&#8217;s a complex topic, I&#8217;ll cover it in a separate article.</p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>This article has introduced Apache Spark, a modern framework for processing and analyzing Big Data on distributed systems. We have covered the basics of Spark&#8217;s architecture and how Spark distributes data and tasks among a computation cluster. Finally, we have looked at how Spark optimizes computations in distributed systems and why it is often necessary to improve things manually. </p>



<p>Now that you have a decent understanding of the essential concepts behind Spark, we can gather hands-on experience. The following article will work with PySpark, the Python-specific interface for Apache Spark. In this tutorial, we will process and analyze weather data using PySpark. </p>



<p><a href="https://www.relataly.com/analyzing-zurich-weather-data-with-python-and-pyspark/2739/">Analyzing Zurich Weather Data with PySpark</a></p>



<p>Thanks for reading, and if you have any questions, please let me know in the comments. </p>



<h2 class="wp-block-heading" id="h-sources-and-further-reading">Sources and Further Reading</h2>



<ol class="wp-block-list"><li><a href="https://amzn.to/3gcImKf" target="_blank" rel="noreferrer noopener">Wenig Damji Das and Lee (2020) Learning Spark: Lightning-fast Data Analytics</a></li><li><a href="https://amzn.to/3exFyHb" target="_blank" rel="noreferrer noopener">Chambers and Zaharu (2018) Spark: The Definitive Guide: Big data processing made simple</a></li><li><a href="https://databricks.com/de/wp-content/uploads/2018/12/nsdi_spark.pdf" target="_blank" rel="noreferrer noopener">Resilient Distributed Datasets: A Fault-Tolerant Abstraction for</a></li><li><a href="https://databricks.com/de/wp-content/uploads/2018/12/nsdi_spark.pdf" target="_blank" rel="noreferrer noopener">In-Memory Cluster Computing.pdf</a></li><li><a href="https://amzn.to/3MAy8j5" target="_blank" rel="noreferrer noopener">Andriy Burkov (2020) Machine Learning Engineering</a></li><li><a href="https://amzn.to/3EKidwE" target="_blank" rel="noreferrer noopener">David Forsyth (2019) Applied Machine Learning Springer</a></li></ol>



<p class="has-contrast-2-color has-base-3-background-color has-text-color has-background"><em>The links above to Amazon are affiliate links. By buying through these links, you support the Relataly.com blog and help to cover the hosting costs. Using the links does not affect the price.</em></p>
<p>The post <a href="https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/">Getting Started with Big Data Analytics &#8211; Apache Spark Concepts and Architecture</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/introduction-to-bigdata-analytics-with-apache-spark-concepts-and-architecture/6324/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6324</post-id>	</item>
	</channel>
</rss>
