#set document(title: "2.5 Frequency Polygons", author: "OpenStax") #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")) == 2.5#h(0.6em)Frequency Polygons #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ #emph[Prerequisites] Histograms #linebreak() #linebreak() ] #notebox("Note", rgb("#8a94a6"), rgb("#556666"), rgb("#f7f8fa"))[ #emph[Learning Objectives] + Create and interpret frequency polygons + Create and interpret cumulative frequency polygons + Create and interpret overlaid frequency polygons ] Frequency polygons are a graphical device for understanding the shapes of distributions. They serve the same purpose as histograms, but are especially helpful for comparing sets of data. Frequency polygons are also a good choice for displaying cumulative frequency distributions. To create a frequency polygon, start just as for histograms, by choosing a class interval. Then draw an X-axis representing the values of the scores in your data. Mark the middle of each class interval with a tick mark, and label it with the middle value represented by the class. Draw the Y-axis to indicate the frequency of each class. Place a point in the middle of each class interval at the height corresponding to its frequency. Finally, connect the points. You should include one class interval below the lowest value in your data and one above the highest value. The graph will then touch the X-axis on both sides. A frequency polygon for 642 psychology test scores shown in Figure 1 was constructed from the frequency table shown in Table 1. Table 1. Frequency Distribution of Psychology Test Scores. #figure(table( columns: 4, align: left, inset: 6pt, table.header([Lower Limit], [Upper Limit], [Count], [Cumulative Count]), [29.5], [39.5], [0], [0], [39.5], [49.5], [3], [3], [49.5], [59.5], [10], [13], [59.5], [69.5], [53], [66], [69.5], [79.5], [107], [173], [79.5], [89.5], [147], [320], [89.5], [99.5], [130], [450], [99.5], [109.5], [78], [528], [109.5], [119.5], [59], [587], [119.5], [129.5], [36], [623], [129.5], [139.5], [11], [634], [139.5], [149.5], [6], [640], [149.5], [159.5], [1], [641], [159.5], [169.5], [1], [642], [169.5], [179.5], [0], [642], )) The first label on the X-axis is 35. This represents an interval extending from 29.5 to 39.5. Since the lowest test score is 46, this interval has a frequency of 0. The point labeled 45 represents the interval from 39.5 to 49.5. There are three scores in this interval. There are 147 scores in the interval that surrounds 85. You can easily discern the shape of the distribution from Figure 1. Most of the scores are between 65 and 115. It is clear that the distribution is not symmetric inasmuch as good scores (to the right) trail off more gradually than poor scores (to the left). In the terminology of Chapter 3 (where we will study shapes of distributions more systematically), the distribution is skewed. #figure(figph[Frequency polygon of the same psychology test scores: points at class midpoints 35 through 175 connected by line segments, frequency 0 at 35, rising to a peak of about 147 at 85, then declining to 0 at 175.], alt: "Frequency polygon of the same psychology test scores: points at class midpoints 35 through 175 connected by line segments, frequency 0 at 35, rising to a peak of about 147 at 85, then declining to 0 at 175.", caption: [Figure 1. Frequency polygon for the psychology test scores.]) A cumulative frequency polygon for the same test scores is shown in Figure 2. The graph is the same as before except that the Y value for each point is the number of students in the corresponding class interval #emph[plus] all numbers in lower intervals. For example, there are no scores in the interval labeled "35," three in the interval "45," and 10 in the interval "55." Therefore, the Y value corresponding to "55" is 13. Since 642 students took the test, the cumulative frequency for the last interval is 642. #figure(figph[Cumulative frequency polygon of the psychology test scores: an S-shaped curve rising from 0 at a test score of 35 to about 640 at 165, steepest between scores of 65 and 95.], alt: "Cumulative frequency polygon of the psychology test scores: an S-shaped curve rising from 0 at a test score of 35 to about 640 at 165, steepest between scores of 65 and 95.", caption: [Figure 2. Cumulative frequency polygon for the psychology test scores.]) Frequency polygons are useful for comparing distributions. This is achieved by overlaying the frequency polygons drawn for different data sets. Figure 3 provides an example. The data come from a task in which the goal is to move a computer cursor to a target on the screen as fast as possible. On 20 of the trials, the target was a small rectangle; on the other 20, the target was a large rectangle. Time to reach the target was recorded on each trial. The two distributions (one for each target) are plotted together in Figure 3. The figure shows that, although there is some overlap in times, it generally took longer to move the cursor to the small target than to the large one. #figure(figph[Overlaid frequency polygons of reaction times for a large target (blue) and a small target (red). The large-target distribution peaks at 10 around 550 msec and reaches 0 by 750 msec; the small-target distribution peaks at about 6 around 650 msec and extends to about 1,050 msec — small-target times are slower and more spread out.], alt: "Overlaid frequency polygons of reaction times for a large target (blue) and a small target (red). The large-target distribution peaks at 10 around 550 msec and reaches 0 by 750 msec; the small-target distribution peaks at about 6 around 650 msec and extends to about 1,050 msec — small-target times are slower and more spread out.", caption: [Figure 3. Overlaid frequency polygons.]) It is also possible to plot two cumulative frequency distributions in the same graph. This is illustrated in Figure 4 using the same data from the cursor task. The difference in distributions for the two targets is again evident. #figure(figph[Overlaid cumulative frequency polygons for the same reaction-time data (20 trials each): the large-target curve (blue) rises earlier, reaching 20 by about 650 msec; the small-target curve (red) reaches 20 by about 1,050 msec.], alt: "Overlaid cumulative frequency polygons for the same reaction-time data (20 trials each): the large-target curve (blue) rises earlier, reaching 20 by about 650 msec; the small-target curve (red) reaches 20 by about 1,050 msec.", caption: [Figure 4. Overlaid cumulative frequency polygons.]) Note that the graphs on this page were not created in R. However, the R code shown here produces very similar graphs. Make sure to put the data files in the default directory. #linebreak() #linebreak() R code written by David Scott Data files for Figures 1 and 2 Data files for Figures 3 and 4 \# Figure 1 tests = read.csv(file = 'psych\_scores.csv') bk = seq(40,170,10) \# bin count interval tk = seq(35,175,10) \# FP "bins" edges nuk = c( 0, hist( (tests\[\[1\]\]), bk, plot=F )\$counts, 0 ) main="Frequency polygon for the psychology test scores" plot(tk,nuk,type="l",col=4,xlab="Test Score",ylab="Frequency",lwd=2,main=main,ylim=c(0,160)) points(tk,nuk,pch=16,col=4,cex=1.5); abline(h=seq(0,160,20),lwd=.5) \# Figure 2 tests = read.csv(file = 'psych\_scores.csv') cum.nuk = cumsum(nuk) main="Cumulative frequency polygon for the psychology test scores" plot(tk,cum.nuk,type="l",col=4,xlab="Test Score",ylab="Cumulative Frequency", lwd=2,main=main,ylim=c(0,700)) points(tk,cum.nuk,pch=16,col=4,cex=1.5); abline(h=seq(0,700,100),lwd=.5) \# Figure 3 target = read.csv(file = 'target\_size.csv') bk = seq(400,1100,100) \# bin count interval tk = seq(350,1150,100) \# FP "bins" edges dat = target\[\[2\]\] \# 1st 20 small 2nd 20 large nuk1 = c( 0, hist( dat\[ 1:20\], bk, plot=F )\$counts, 0 ) nuk2 = c( 0, hist( dat\[21:40\], bk, plot=F )\$counts, 0 ) main="Overlaid Frequency polygons" plot(tk,nuk1,type="l",col=2,xlab="Time (msec)",ylab="Frequency",lwd=2,main=main,ylim=c(0,10)) points(tk,nuk1,pch=16,col=2,cex=2); abline(h=seq(0,10,2.5),lwd=.5,lty=2) lines(tk,nuk2,col=4); points(tk,nuk2,pch=16,cex=2,col=4) text(1000,4,"small target",cex=1.5) text(720,8,"large target",cex=1.5) \# Figure 4 target = read.csv(file = 'target\_size.csv') cum.nuk1 = cumsum(nuk1) cum.nuk2 = cumsum(nuk2) main="Overlaid cumulative frequency polygons" plot(tk,cum.nuk1,type="l",col=2,xlab="Time (msec)", ylab="Cumulative Frequency", lwd=2,main=main,ylim=c(0,20)) points(tk,cum.nuk1,pch=16,col=2,cex=2); abline(h=seq(0,20,5)) lines(tk,cum.nuk2,col=4,lwd=2); points(tk,cum.nuk2,pch=16,col=4,cex=2) text(850,12,"small target",cex=1.5) text(450,18,"large target",cex=1.5)