#set document(title: "9.2 Encoding Data That Change Over Time", author: "OpenStax / XYZ Homework") #set page(width: 8.5in, height: auto, margin: 1in) #import "@preview/cetz:0.5.2" #set text(font: ("STIX Two Text", "Libertinus Serif", "New Computer Modern"), size: 10.5pt, lang: "en") #show math.equation: set text(font: ("STIX Two Math", "New Computer Modern Math")) #set par(justify: true, leading: 0.62em, spacing: 0.9em) #set enum(spacing: 1.1em) // room between list items so tall inline fractions don't collide #set list(spacing: 1.1em) #set table(stroke: 0.5pt + rgb("#c7ccd3")) #let BLUE = rgb("#183B6F") // brand navy — section bars + example/solution labels (white on navy 11.09:1) #let ORANGE = rgb("#A94509") // brand primary-700 — AA-safe deep orange for TEXT (5.93:1 on white; raw brand #F37021 is 2.94:1 and must never carry text) #let RED = rgb("#DC2626") // brand error-600 #let GREEN = rgb("#059669") // brand success-600 (decoration only; small green text uses green-text #007942) #show heading.where(level: 1): it => block(width: 100%, above: 0pt, below: 16pt, fill: gradient.linear(BLUE, rgb("#2C5AA0")), inset: (x: 14pt, y: 12pt), radius: 3pt, text(fill: white, weight: "bold", size: 19pt, it.body)) #show heading.where(level: 2): it => block(width: 100%, above: 18pt, below: 10pt, fill: BLUE, inset: (x: 10pt, y: 6pt), radius: 2pt, text(fill: white, weight: "bold", size: 12pt, it.body)) #show heading.where(level: 3): it => text(fill: ORANGE, weight: "bold", size: 12.5pt, it.body) #show heading.where(level: 4): it => text(fill: BLUE, weight: "bold", size: 10.5pt, it.body) #let examplebox(label, title, body) = block(width: 100%, breakable: true, fill: rgb("#EFF1F5"), stroke: 0.5pt + rgb("#CFDDF0"), radius: 4pt, inset: 10pt, above: 12pt, below: 12pt)[ #block(below: 6pt)[#box(fill: BLUE, inset: (x: 6pt, y: 2pt), radius: 2pt, text(fill: white, weight: "bold", size: 8.5pt, label)) #h(0.4em) #strong[#title]] #body] // rail = decorative left rule (raw brand token); labelcolor = AA-safe label text shade #let notebox(label, rail, labelcolor, tint, body) = block(width: 100%, breakable: true, fill: tint, stroke: (left: 3pt + rail), inset: (left: 10pt, rest: 8pt), radius: (right: 4pt), above: 11pt, below: 11pt)[ #text(fill: labelcolor, weight: "bold", size: 7.5pt, tracking: 0.5pt)[#upper(label)] #linebreak() #body] #let solutionbox(body) = block(above: 4pt, below: 8pt)[ #text(fill: BLUE, weight: "bold", size: 8.5pt)[Solution] #linebreak() #body] #let figph(msg) = block(width: 100%, height: 60pt, fill: rgb("#f6f7f9"), stroke: (paint: rgb("#c7ccd3"), dash: "dashed"), radius: 4pt, inset: 10pt)[ #align(center + horizon, text(fill: rgb("#889"), style: "italic", size: 9pt, msg))] // Standardize inlined figure sizes: measure the natural CeTZ canvas, then scale to a // consistent envelope (aspect-aware; see build_typst.py FIG_* constants). Unlike the // print preamble, dimensions are FLOORED: in an editor a user can trim a figure to a // degenerate 1-D shape (a bare line), and w/h or tw/w would then divide by zero. #let _STD_W = 3.5 #let _WIDE_W = 5.6 #let _MAX_H = 3.4 #let _ASPECT_WIDE = 2.2 #let _UPSCALE_MAX = 1.15 #let stdfig(body) = context { let m = measure(body) let w = calc.max(m.width / 1in, 0.01) let h = calc.max(m.height / 1in, 0.01) let tw = if w / h > _ASPECT_WIDE { _WIDE_W } else { _STD_W } let s = calc.min(tw / w, _MAX_H / h, _UPSCALE_MAX) align(center, box(scale(x: s * 100%, y: s * 100%, reflow: true, body))) } #show figure: set block(breakable: false) #set figure(gap: 8pt) #show figure.caption: set text(size: 8.5pt, fill: rgb("#555")) == 9.2#h(0.6em)Encoding Data That Change Over Time === Learning Outcomes By the end of this section, you should be able to: - Create and interpret labeled graphs to visually identify trends in data over time. - Use Python to generate various data visualizations for time series data. Researchers are frequently interested in analyzing and interpreting data over time. Recall from Time and Series Forecasting that any set of data that consists of numerical measurements of the same variable collected and organized according to regular time intervals may be regarded as #emph[time series]data. A time series graph allows data scientists to visually identify trends in data over time. For example, a college administrator is very interested in tracking enrollment data from semester to semester. A marketing manager is interested in tracking quarterly revenue for a business. An investor might be interested in tracking stock prices on a monthly basis. In many cases, a time series graph can reveal seasonal patterns to cycles, which is important information to help guide many business decisions, such as planning marketing campaigns or setting optimal inventory levels. Time series graphs also provide important data for forecasting methods, which attempts to predict future trends based on past data. Refer to Examples of Time Series Data for the basics of visualizing time series data in Excel and Python. The Trend Curve and Trend-Cycle Component explores visualization of a trend curve. Here we’ll explore line charts, trend curves, and the use of Python for time series data visualization in more detail. === Line Charts and Trend Curves A time series graph is used in many fields such as finance, health care, economics, etc. to visualize data measurements over time. To construct a time series graph, the horizontal axis is used to plot the time increments, and the vertical axis is used to plot the values of the variable that we are measuring, such as revenue, enrollment, inventory level, etc. By doing this, we make each point on the graph correspond to a point in time and a measured quantity. The points on the graph are typically connected by straight lines in the order in which they occur. Once the chart is created, a researcher can identify trends or patterns in the data to help guide decision-making. #examplebox("Example 1")[][ The following data plots the enrollment at a community college over an eight-year time period. Create a times series graph of the data and comment on any trends . #figure(table( columns: 2, align: left, inset: 6pt, table.header([#strong[Year]], [#strong[Enrollment]]), [1], [8641], [2], [9105], [3], [9361], [4], [9895], [5], [9230], [6], [8734], [7], [8104], [8], [7743], )) #solutionbox[ To create a time series graph for this dataset, start off by creating the horizontal axis by plotting the time increments, from years 1 to 8. For the vertical axis, used a numeric scale extending from 4,000 to 12,000 since this covers the span of the numeric enrollment data. Then for each row in the table, plot the corresponding #math.equation(block: false, alt: "open parenthesis x , y close parenthesis")[$( x , y )$] point on the graph. By doing this, we make each point on the graph correspond to a point in time and a measured quantity. For example, the first row in the table shows the #math.equation(block: false, alt: "open parenthesis x , y close parenthesis")[$( x , y )$] datapoint of (1, 8641). To plot this point, identify the location that corresponds to Year 1 on the horizontal axis and an enrollment value of 8641 on the vertical axis. At the intersection of the horizontal location and vertical location, plot a single point to represent this #math.equation(block: false, alt: "open parenthesis x , y close parenthesis")[$( x , y )$] data value. Repeat this process for each row in the table. Since there are eight rows in the table, we expect to see eight points on the time series graph. Finally, the points on the graph are typically connected by straight lines in the order in which they occur (see the Python output from Example 2). ] ] === Using Python for Times Series Data Visualization Data visualization is a very important part of data science, and Python has many built-in graphing capabilities through a package called matplotlib. To import this package into a Python program, use the command: import matplotlib.pyplot as plt Matplotlib contains functions such as plot that can be used to generate time series graphs. After defining the #math.equation(block: false, alt: "open parenthesis x , y close parenthesis")[$( x , y )$] data to be graphed, the Python function plt.plot(x, y) can be used to generate the time series chart. #examplebox("Example 2")[][ Use the plot function in Python to create a time series graph for the dataset shown in Example 1. #solutionbox[ In the following Python code, note that the plt.plot with marker specifies that points should be plotted at the various #math.equation(block: false, alt: "open parenthesis x , y close parenthesis")[$( x , y )$] points. In addition, plt.ylim specifies the range for the #emph[y]-axis. #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ \# import the matplotlib library import matplotlib.pyplot as plt import matplotlib.ticker as ticker \# Define the x-data x = \[1, 2, 3, 4, 5, 6, 7, 8\] \# Define the y-data y = \[8641, 9105, 9361, 9895, 9230, 8734, 8104, 7743\] \# Use the plot function to generate a time series graph plt.plot(x, y, marker='o', linestyle='-') \# Set the scale for the y-axis plt.ylim(6000, 11000)  \# This sets the y-axis range from 6000 to 11000 \# Define a function to format the ticks with commas as thousands separators def format\_ticks(value, tick\_number):     return f'{value:,.0f}' \# Apply the custom formatter to the y-axis plt.gca().yaxis.set\_major\_formatter(ticker.FuncFormatter(format\_ticks)) \# Add labels to the x and y axes by using xlabel and ylabel functions plt.xlabel("Year") plt.ylabel("Enrollment") \# Add a title using the title function plt.title("Enrollment at a Community College") \# Show the plot plt.show() The resulting output will look like this: #figure(figph[A line graph labeled enrollment at a community college. The X axis representing years ranges from 1 to 8 and the Y axis for enrollment ranges from 6,000 to 12,000. The line created by the 8 data points indicates that the enrollment started at about 8,600, gradually increased over years 1 to 4 to a peak of 9,800, then began to decrease from years 4 to 8 to a low around 7,700.], alt: "A line graph labeled enrollment at a community college. The X axis representing years ranges from 1 to 8 and the Y axis for enrollment ranges from 6,000 to 12,000. The line created by the 8 data points indicates that the enrollment started at about 8,600, gradually increased over years 1 to 4 to a peak of 9,800, then began to decrease from years 4 to 8 to a low around 7,700.", caption: none) The graph indicates that the enrollment gradually increased over years 1 to 4 but then began to decrease from years 4 to 8. ] ] ] === Guidelines for Creating Effective Visualizations You have likely come across poorly constructed graphs that are difficult to interpret or possibly misleading in some way. However, if you follow certain guidelines when creating your visualizations, you will be sure your visualizations are effective and represent the data fairly. The first rule is to ensure your graph or chart is clear and easy to understand. You may be familiar with the type of data collected, but your audience may not be. Provide a title and label each axis, including units where appropriate. Provide a data source where appropriate. Use scales for the axes and avoid distortion (i.e., don’t intentionally adjust the scale to produce a desired effect in the graph). The use of colors to differentiate data can be an important part of graphs and displays. Overall, the use of color can make the visualization more appealing and engaging for the viewer. However, there are some important things to keep in mind when using color. Be sure to apply color consistently to represent the same categories. Ensure that there is contrast between different colors to make them easily distinguishable. For example, if you used various shades of blue for the sectors in a pie chart, it might be difficult for the reader to distinguish among them. Keep in mind that some viewers may be color-blind, so it’s a good rule of thumb to use color palettes that are accessible to color-blind individuals. The most basic rule for a color-blind palette is to avoid combining green and red. #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ #emph[Resources for Creating Color-Blind Palettes] - The Dataviz Best Practices blog includes tips on creating #link("https://openstax.org/r/datylon")[The Best Charts for Colorblind Viewers]. - #link("https://openstax.org/r/colorblindguide")[10 Essential Guidelines for Colorblind Friendly Design] offers more information on types of color-blindness and ways to make your visual design accessible for and appealing to color-blind users. ] You should also be aware that colors can have different meanings in different cultures. Keep the number of colors used in your visual to a minimum. One rule of thumb is to limit the number of colors to three to five to avoid a color palette that is too confusing. Create the graph with your audience in mind. If the graph is intended for a general audience, then the graph should be as simple as possible and easy to interpret, perhaps with pie charts or bar charts. Don’t include too many categories in your pie chart; if you have more than about five or six categories, you may want to consider a different type of chart. Consider combining categories where appropriate for simplicity. (Sometimes an “other” category can be used to combine categories with very few counts.) If the graph is intended for a more technical audience or for more complicated types of analyses, then a more detailed display such as a scatterplot with regression line and confidence bounds may be appropriate. (Visualizing data with scatterplots is covered in Multivariate and Network Data Visualization Using Python.) === Selecting the Best Type of Visualization When creating graphs and displays to visualize data, the data scientist must consider what type of graph will work best with the collected data and will best convey the message that the data reveals. This section provides some guidance on the optimal type of graph for different scenarios. Before we discuss how to choose the best visualization, it is important to consider the type of data being presented. Recall that data can be divided into the broad categories of #emph[#strong[qualitative data]] (describes categories or groups) and #emph[#strong[quantitative data]] (numeric data) and that quantitative data is further classified as #emph[#strong[discrete]] (usually counts) and #emph[#strong[continuous]] (usually measurements that can take on any value within a range). You first need to be clear about the type of data being illustrated. Then, carefully consider the goal of the visualization—that is, what are you trying to accomplish with the graph or display? What is your data telling you? How is it distributed, and what patterns or relationships do you want to highlight? You might be interested in comparing different groups of categories, or you may be interested in showing how data is distributed over some interval. Recall from the previous discussion of correlation and regression that we are often interested in showing correlations or relationships between quantitative variables. offers some suggestions for picking the most appropriate graphing method based on your goals and type of data. #figure(table( columns: 3, align: left, inset: 6pt, table.header([#strong[Goal of Visualization]], [#strong[Type of Data]], [#strong[Visualization Methods to Consider]]), [Show a comparison of different groups or categories], [Qualitative or Quantitative], [Bar charts are useful for comparing different groups of categories Column chart], [Show correlations or relationships between quantitative variables], [Quantitative], [Scatterplot Time series graph Heatmap], [Show how a whole is divided into parts], [Quantitative], [Pie chart], [Show how data is distributed over some interval], [Quantitative], [Histogram Boxplot], ))