The Art of Data Visualization — Weather Data Visualization Using Matplotlib and Ggplot2 | by Benjamin Obi Tayo Ph.D. | Towards Data Science

Data Visualization is more of an Art than Science. To produce a good visualization, you need to put several pieces of code together for an excellent end result. This tutorial demonstrates how a good data visualization can be produced by analyzing weather data.
In Section I, we produce a visualization using matplotlib package. In Section II, we attempt to reproduce the visualization using ggplot2.
Before delving into the art of data visualization, lets first discuss the essential components of a good data visualization.
A good data visualization is made up of several components that have to be pieced up together to produce an end product:
a) Data Component: An important first step in deciding how to visualize data is to know what type of data it is, e.g. categorical data, discrete data, continuous data, time series data, etc.
b) Geometric Component: Here is where you decide what kind of visualization is suitable for your data, e.g. scatter plot, line graphs, barplots, histograms, qqplots, smooth densities, boxplots, pairplots, heatmaps, etc.
c) Mapping Component: Here you need to decide what variable to use as your x-variable and what to use as your y-variable. This is important especially when your dataset is multi-dimensional with several features.
d) Scale Component: Here you decide what kind of scales to use, e.g. linear scale, log scale, etc.
e) Labels Component: This include things like axes labels, titles, legends, font size to use, etc.
f) Ethical Component: Here, you want to make sure your visualization tells the true story. You need to be aware of your actions when cleaning, summarizing, manipulating and producing a data visualization and ensure you aren’t using your visualization to mislead or manipulate your audience.
This article will compare the strengths of Python’s Matplotlib and R’s ggplot2 package for analyzing and visualizing weather data.
The code will perform the following data visualization tasks:
It returns a line graph of the record high and records low temperatures by day of the year over the period 2005–2014. The area between the record high and record low temperatures for each day of the year is shaded.Overlays a scatter of the 2015 data for any points (highs and lows) for which the ten-year record (2005–2014) record high or record low was broken in 2015.
It returns a line graph of the record high and records low temperatures by day of the year over the period 2005–2014. The area between the record high and record low temperatures for each day of the year is shaded.
Overlays a scatter of the 2015 data for any points (highs and lows) for which the ten-year record (2005–2014) record high or record low was broken in 2015.
Dataset: The NOAA dataset used for this project is stored in the file weather_data.csv. This data comes from a subset of the National Centers for Environmental Information (NCEI) Daily Global Historical Climatology Network (GHCN-Daily). The GHCN-Daily is comprised of daily climate records from thousands of land surface stations across the globe. The data was collected from data stations near Ann Arbor, Michigan, United States.
The complete code for this article can be downloaded from this repository: https://github.com/bot13956/weather_pattern.
import matplotlib.pyplot as pltimport pandas as pdimport numpy as npdf=pd.read_csv('weather_data.csv')df.head()
#convert temperature from tenths of degree C to degree Cdf['Data_Value']=0.1*df.Data_Valuedays=list(map(lambda x: x.split('-')[-2]+'-'+x.split('-')[-1], df.Date))years=list(map(lambda x: x.split('-')[0], df.Date))df['Days']=days df['Years']=yearsdf_2005_to_2014=df[(df.Days!='02-29')&(df.Years!='2015')]df_2015=df[(df.Days!='02-29')&(df.Years=='2015')]df_max=df_2005_to_2014.groupby(['Element','Days']).max()df_min = df_2005_to_2014.groupby(['Element','Days']).min()df_2015_max=df_2015.groupby(['Element','Days']).max()df_2015_min = df_2015.groupby(['Element','Days']).min()record_max=df_max.loc['TMAX'].Data_Valuerecord_min=df_min.loc['TMIN'].Data_Valuerecord_2015_max=df_2015_max.loc['TMAX'].Data_Valuerecord_2015_min=df_2015_min.loc['TMIN'].Data_Value
plt.figure(figsize=(10,7))plt.plot(np.arange(len(record_max)),record_max, '--k', label="record high")plt.plot(np.arange(len(record_max)),record_min, '-k',label="record low")plt.scatter(np.where(record_2015_min < record_min.values),            record_2015_min[record_2015_min <             record_min].values,c='b',label='2015 break low')plt.scatter(np.where(record_2015_max > record_max.values),            record_2015_max[record_2015_max >                  record_max].values,c='r',label='2015 break high')plt.xlabel('month',size=14)plt.ylabel('temperature($^\circ C$ )',size=14)plt.xticks(np.arange(0,365,31),          ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug',              'Sep','Oct','Nov','Dec'])ax=plt.gca()ax.axis([0,365,-40,40])plt.gca().fill_between(np.arange(0,365),                        record_min, record_max,                        facecolor='blue',                        alpha=0.25)plt.title('Record temperatures for different months between 2005-2014',size=14)plt.legend(loc=0)plt.show()
I was wondering, can I produce a similar visualization of the figure above using R’s ggplot2 package?
So I decided to perform a similar analysis to see how close I can get with ggplot2.
library(tidyverse)library(readr)df<-read.csv("weather_data.csv")
#convert temperature from tenths of degree C to degree Cdf$Data_Value = 0.1*df$Data_Value #functions to split date split_function<-function(x)unlist(strsplit(x,'-'))year_function<-function(x)split_function(x)[1]day_function<-function(x)paste(split_function(x[2],                               split_function(x)[3],sep='-') #create Day and Year columns day<-sapply(as.vector(df$Date),day_function)year<-sapply(as.vector(df$Date),year_function)df<-df%>%mutate(Day=day,Year=year ) #filter leap year and select 10 year observation period: 2005-2014 df_2005_to_2014<-df%>%filter((df$Day!='02-29') (df$Year!='2015'))df_2015<-df%>%filter((df$Day!='02-29')&(df$Year=='2015')) #record min and max for each day of the year for the 2005-2014 period record_max<-df_2005_to_2014%>%group_by(Day)%>%summarize(Max = max(Data_Value),Min=min(Data_Value))%>%.$Maxrecord_min<-df_2005_to_2014%>%group_by(Day)%>%summarize(Max = max(Data_Value),Min=min(Data_Value))%>%.$Min #record min and max for each day of the year for 2015 record_2015_max<-df_2015%>%group_by(Day)%>%summarize(Max = max(Data_Value),Min=min(Data_Value))%>%.$Maxrecord_2015_min<-df_2015%>%group_by(Day)%>%summarize(Max = max(Data_Value),Min=min(Data_Value))%>%.$Min
#data frame for the 2005-2014 temperatures y<-c(seq(1,1,length=365),seq(2,2,length=365))y<-replace(replace(y, seq(1,365),'max'),seq(366,730),'min')values<-data.frame(day=c(seq(1,365), seq(1,365)),element=sort(y),Temp=c(record_max,record_min))q<-values%>%mutate(element=factor(element))#data frame for the 2015 temperatures max_index<-which(record_2015_max>record_max)min_index<-which(record_2015_min < record_min)dat15_max<data.frame(max_index=max_index,                     Tmax=record_2015_max[max_index])dat15_min<-data.frame(min_ndex=min_index,                        Tmin=record_2015_min[min_index])
q%>%ggplot(aes(day,Temp,color=element))+    geom_line(size=1,show.legend = TRUE)+    geom_point(data=dat15_max,               aes(max_index,Tmax,color='max_index'),               size=2,show.legend = TRUE)+            geom_point(data=dat15_min,               aes(min_index,Tmin,color='min_index'),               size=2,show.legend = TRUE)+      scale_colour_manual(labels=c("record high","2015 break                 high","record low","2015 break low"),               values=c('red','purple','blue','green'))+        xlab('Month')+     ylab('Temperature (C)')+      scale_x_continuous(breaks = as.integer(seq(1,335,length=12)),            labels=c('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug',             'Sep','Oct','Nov','Dec'))+     ggtitle("Record temperatures between 2005-2014")+      theme(        plot.title = element_text(color="black", size=12, hjust=0.5,                                     face="bold"),        axis.title.x = element_text(color="black", size=12,                                   face="bold"),         axis.title.y = element_text(color="black", size=12,                                   face="bold"),        legend.title = element_blank())
Here is the output using R’s ggplot2:
I tried my best to produce a visualization using R’s ggplot2 package that is very similar to that produced with Python’s Matplotlib.
It seems to me that for this particular project, Matplotlib produces a better and more beautiful visualization compared to R’s ggplot2 package. Using matplotlib, the visualization was produced with fewer effort (lines of code), compared to ggplot2.
If you are interested in downloading the source code for Matplotlib and ggplot2 executions, please visit the following Github repository: https://github.com/bot13956/weather_pattern.
Please leave feedback comments for suggestions on how to improve the ggplot2 visualization. I am pretty sure the quality could be improved.