Show
Slope GraphsThe most used graph for visualizing the relationship between two numeric variables is the scatter plot. But there is one alternative that can be useful and is increasingly popular: the slope chart or slope graph. Tufte’s Slope GraphTwo articles on slope graphs with examples:
Tufte showed this example in The Visual Display of Quantitative Information: Some features of the data that are easy to see:
The chart uses no non-data ink. The chart in this form is well suited for small data sets or summaries with modest numbers of categories. Scalability in this full form is limited, but better if labels and values are dropped. The idea can be extended to multiple periods, though two periods or levels is most common when labeling is used. Without labeling this becomes a parallel coordinates plot. Barley Mean YieldsA slope graph for the average yields at each experiment station for the two years 1931 and 1932: theme_set(theme_minimal() + theme(text = element_text(size = 16))) library(ggrepel) barley_site_year <- group_by(barley, site, year) %>% summarize(avg_yield = mean(yield)) %>% mutate(year = fct_rev(year)) barley_site_year_1932 <- filter(barley_site_year, year == "1932") ggplot(barley_site_year, aes(x = year, y = avg_yield, group = site)) + geom_line() + geom_text_repel(aes(label = site), data = barley_site_year_1932, hjust = "left", direction = "y") + scale_x_discrete(expand = expand_scale(mult = c(0.1, .25)), position = "top") + labs(x = NULL, y = "Average Yield")The anomalous result for Morris pops out very clearly. This graph departs from the classic Tufte style:
This is similar to the style used here. Creating the GraphThe first step is to compute the averages: barley_site_year <- group_by(barley, site, year) %>% summarize(avg_yield = mean(yield)) head(barley_site_year, 2)The year variable is a factor with the levels in the wrong order, so we need to fix that: levels(barley_site_year$year) barley_site_year <- mutate(barley_site_year, year = fct_rev(year)) levels(barley_site_year$year)Set the default theme to theme_minimal with larger text: theme_set(theme_minimal() + theme(text = element_text(size = 16)))The core of a slope graph is produced by p <- ggplot(barley_site_year, aes(x = year, y = avg_yield, group = site)) + geom_line() pAdding the labels on the 1932 side can be done as barley_site_year_1932 <- filter(barley_site_year, year == "1932") p + geom_text(aes(label = site), data = barley_site_year_1932, hjust = "left")The label positions could use further adjusting. Using geom_text_repel from the ggrepel package handles this well: library(ggrepel) p <- p + geom_text_repel(aes(label = site), data = barley_site_year_1932, hjust = "left", direction = "y") pAdjust the x scale: p <- p + scale_x_discrete(expand = expand_scale(mult = c(0.1, .25)), position = "top") pFinal theme adjustments: p + labs(x = NULL, y = "Average Yield")Father-Son HeightsThe father.son data set has 1078 observations, which is too large for the labeled slope graph, but the basic representation is useful: fs <- mutate(father.son, id = seq_len(nrow(father.son))) %>% pivot_longer(1:2, names_to = "which", values_to = "height") ggplot(fs, aes(x = which, y = height)) + geom_line(aes(group = id), alpha = 0.1) + scale_x_discrete(expand = expand_scale(mult = c(.1, .1)), labels = c("Father", "Son"), position = "top") + labs(x = NULL, y = "Height (Inches)")This very clearly shows the famous regression to the mean effect:
Conversely,
Creating the GraphTo make creating the graph easier we can convert the data frame into a longer form with variables
Add the id variable: fs <- mutate(father.son, id = seq_len(nrow(father.son))) head(fs)Pivot to the longer format: fs <- pivot_longer(fs, 1:2, names_to = "which", values_to = "height") head(fs)The basic plot is quite simple: ggplot(fs, aes(x = which, y = height, group = id)) + geom_line()With an alpha adjustment to reduce over-plotting: p <- ggplot(fs, aes(x = which, y = height, group = id)) + geom_line(alpha = 0.1) pWith an axis adjustment and using a reduced alpha level: p + scale_x_discrete(expand = expand_scale(mult = c(.1, .1)), labels = c("Father", "Son"), position = "top") + labs(x = NULL, y = "Height (Inches)")Scatter PlotsA scatter plot of two variables maps the values of one variable to the vertical axis and the other to the horizontal axis of a cartesian coordinate system and places a mark for each observation at the resulting point. Conventions:
Barley YieldsFor a scatter plot of mean yield in 1932 against mean yield in 1931 for the different sites it is useful to have a data frame containing variables for each year. This requires converting the data frame to a wider format. wide_barley_site_year <- pivot_wider(barley_site_year, names_from = "year", names_prefix = "avg_yield_", values_from = "avg_yield") head(wide_barley_site_year) ## # A tibble: 6 x 3 ## # Groups: site [6] ## site avg_yield_1932 avg_yield_1931 ## <fct> <dbl> <dbl> ## 1 Grand Rapids 20.8 29.1 ## 2 Duluth 25.7 30.3 ## 3 University Farm 29.5 35.8 ## 4 Morris 41.5 29.3 ## 5 Crookston 31.2 43.7 ## 6 Waseca 41.9 54.3The basic scatter plot of y = avg_yield_1932 against x = avg_yield_year1931: p <- ggplot(wide_barley_site_year, aes(x = avg_yield_1931, y = avg_yield_1932)) + geom_point() pAdding labels using geom_text_repel identifies the Morris site: p <- p + geom_text_repel(aes(label = site), vjust = "top") pTo recognize the reversal for Morris we can add the 45 degree line: p + geom_abline(aes(intercept = 0, slope = 1), linetype = 2)A 45 degree line also helps when viewing the full data: bw <- pivot_wider(barley, names_from = "year", names_prefix = "yield_", values_from = "yield") ggplot(bw, aes(x = yield_1931, y = yield_1932)) + geom_point() + geom_abline(intercept = 0, slope = 1, linetype = 2) + geom_point(data = filter(bw, site == "Morris"), color = "red") + ggtitle("Barley Yields", "Values for Morris are shown in red.") + labs(x = "1931", y = "1932")A recent blog post discusses the value of reference lines as plot annotations. If the primary goal is to show the change from one year to the next then a mean-difference plot is a good choice: ggplot(wide_barley_site_year, aes(x = (avg_yield_1932 + avg_yield_1931) / 2, y = avg_yield_1932 - avg_yield_1931)) + geom_point() + geom_text_repel(aes(label = site), vjust = "top") + geom_abline(aes(intercept = 0, slope = 0), linetype = 2)For the full data: ggplot(bw, aes(x = (yield_1932 + yield_1931) / 2, y = yield_1932 - yield_1931)) + geom_point() + geom_abline(aes(intercept = 0, slope = 0), linetype = 2)The comparison of changes is now an aligned axis comparison. Mean-difference plots are also known as
Plotting the difference against the x variable is also often useful: ggplot(bw, aes(x = yield_1931, y = yield_1932 - yield_1931)) + geom_point() + geom_point(data = filter(bw, site == "Morris"), color = "red") + geom_abline(aes(intercept = 0, slope = 0), linetype = 2) + ggtitle("Barley Yield Differences", "Values for Morris are shown in red.") + labs(x = "Yield in 1931", y = "Difference in Yield for 1932")Father and Son HeightsThe basic scatter plot: p0 <- ggplot(father.son, aes(x = fheight, y = sheight)) p1 <- p0 + geom_point() p1Adding a line with slope one helps identify the regression to the mean phenomenon: Adding a regression line helps further: p2 + geom_smooth(method = "lm")But for showing the regression effect it is hard to beat the scatter plot of sheight - fheight against fheight: ggplot(father.son) + geom_point(aes(x = fheight, y = sheight - fheight)) + geom_hline(aes(yintercept = 0), linetype = 2)Old Faithful EruptionsA scatter plot of the waiting times until the next eruption against the duration of the current eruption for the faithful data set shows the two clusters corresponding to the short and long eruptions: ggplot(faithful) + geom_point(aes(x = eruptions, y = waiting))For the geyser data set from the MASS package a plot of the two variables shows a different pattern: ggplot(geyser) + geom_point(aes(x = duration, y = waiting))The reason for the difference is that in the geyser data set the waiting time reflects the time since the previous eruption, not the time until the next one. For this ordering it is more natural to plot duration against waiting: ggplot(geyser) + geom_point(aes(x = waiting, y = duration))How well does the waiting time predict whether the duration will be longer or shorter? The question the park service is more interested in is how well duration predict waiting time until the next eruption. We can adjust these data to pair durations with waiting times until the next eruption using the lag function from dplyr. This produces the same basic pattern as for the faithful data set: ggplot(geyser) + geom_point(aes(x = lag(duration), y = waiting)) ## Warning: Removed 1 rows containing missing values (geom_point).LS0tCnRpdGxlOiAiVmlzdWFsaXppbmcgVHdvIE51bWVyaWMgVmFyaWFibGVzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgotLS0KCmBgYHtyIGdsb2JhbF9vcHRpb25zLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoY29sbGFwc2U9VFJVRSkKYGBgCgpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQpsaWJyYXJ5KFVzaW5nUikKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShncmlkRXh0cmEpCnNldC5zZWVkKDEyMzQ1KQpgYGAKCgojIyBTbG9wZSBHcmFwaHMKClRoZSBtb3N0IHVzZWQgZ3JhcGggZm9yIHZpc3VhbGl6aW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28KbnVtZXJpYyB2YXJpYWJsZXMgaXMgdGhlIF9zY2F0dGVyIHBsb3RfLgoKQnV0IHRoZXJlIGlzIG9uZSBhbHRlcm5hdGl2ZSB0aGF0IGNhbiBiZSB1c2VmdWwgYW5kIGlzIGluY3JlYXNpbmdseQpwb3B1bGFyOiB0aGUgX3Nsb3BlIGNoYXJ0XyBvciBfc2xvcGUgZ3JhcGhfLgoKCiMjIyBUdWZ0ZSdzIFNsb3BlIEdyYXBoCgpUd28gYXJ0aWNsZXMgb24gc2xvcGUgZ3JhcGhzIHdpdGggZXhhbXBsZXM6CgoqIGh0dHA6Ly9jaGFybGllcGFyay5vcmcvc2xvcGVncmFwaHMvCiogaHR0cDovL3d3dy52aXN1YWxpc2luZ2RhdGEuY29tLzIwMTMvMTIvaW4tcHJhaXNlLW9mLXNsb3BlZ3JhcGhzLwoKVHVmdGUgc2hvd2VkIHRoaXMgZXhhbXBsZSBpbiBfVGhlIFZpc3VhbCBEaXNwbGF5IG9mIFF1YW50aXRhdGl2ZQpJbmZvcm1hdGlvbl86CgohW10oaW1nL3R1ZnRlc2xvcGUuZ2lmKQo8IS0tIGh0dHA6Ly9jaGFybGllcGFyay5vcmcvaW1hZ2VzL3Nsb3BlZ3JhcGhzL3Nsb3BlZ3JhcGguZ2lmIC0tPgoKU29tZSBmZWF0dXJlcyBvZiB0aGUgZGF0YSB0aGF0IGFyZSBlYXN5IHRvIHNlZToKCiogb3JkZXIgb2YgdGhlIGNvdW50cmllcyB3aXRoaW4gZWFjaCB5ZWFyOwoKKiBob3cgZWFjaCBjb3VudHJ5J3MgdmFsdWVzIGNoYW5nZWQ7CgoqIGhvdyB0aGUgcmF0ZXMgb2YgY2hhbmdlIGNvbXBhcmU7CgoqIHRoZSBjb3VudHJ5IChCcml0YWluKSB0aGF0IGRvZXMgbm90IGZpdCB0aGUgZ2VuZXJhbCBwYXR0ZXJuLgoKVGhlIGNoYXJ0IHVzZXMgbm8gbm9uLWRhdGEgaW5rLgoKVGhlIGNoYXJ0IGluIHRoaXMgZm9ybSBpcyB3ZWxsIHN1aXRlZCBmb3Igc21hbGwgZGF0YSBzZXRzIG9yIHN1bW1hcmllcwp3aXRoIG1vZGVzdCBudW1iZXJzIG9mIGNhdGVnb3JpZXMuCgpTY2FsYWJpbGl0eSBpbiB0aGlzIGZ1bGwgZm9ybSBpcyBsaW1pdGVkLCBidXQgYmV0dGVyIGlmIGxhYmVscyBhbmQKdmFsdWVzIGFyZSBkcm9wcGVkLgoKVGhlIGlkZWEgY2FuIGJlIGV4dGVuZGVkIHRvIG11bHRpcGxlIHBlcmlvZHMsIHRob3VnaCB0d28gcGVyaW9kcyBvcgpsZXZlbHMgaXMgbW9zdCBjb21tb24gd2hlbiBsYWJlbGluZyBpcyB1c2VkLiBXaXRob3V0IGxhYmVsaW5nIHRoaXMKYmVjb21lcyBhIF9wYXJhbGxlbCBjb29yZGluYXRlcyBwbG90Xy4KCiFbXShpbWcvY2FuY2VyX3N1cnZpdmFsX25hc2guZ2lmKQoKPCEtLQpodHRwOi8vY2hhcmxpZXBhcmsub3JnL2ltYWdlcy9zbG9wZWdyYXBocy9jYW5jZXJfc3Vydml2YWxfbmFzaC5naWYKLS0+CgoKIyMjIEJhcmxleSBNZWFuIFlpZWxkcwoKQSBzbG9wZSBncmFwaCBmb3IgdGhlIGF2ZXJhZ2UgeWllbGRzIGF0IGVhY2ggZXhwZXJpbWVudCBzdGF0aW9uIGZvcgp0aGUgdHdvIHllYXJzIDE5MzEgYW5kIDE5MzI6CgpgYGB7cn0KdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSArIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkpCmxpYnJhcnkoZ2dyZXBlbCkKYmFybGV5X3NpdGVfeWVhciA8LSBncm91cF9ieShiYXJsZXksIHNpdGUsIHllYXIpICU+JQogICAgc3VtbWFyaXplKGF2Z195aWVsZCA9IG1lYW4oeWllbGQpKSAlPiUKICAgIG11dGF0ZSh5ZWFyID0gZmN0X3Jldih5ZWFyKSkKYmFybGV5X3NpdGVfeWVhcl8xOTMyIDwtIGZpbHRlcihiYXJsZXlfc2l0ZV95ZWFyLCB5ZWFyID09ICIxOTMyIikKZ2dwbG90KGJhcmxleV9zaXRlX3llYXIsIGFlcyh4ID0geWVhciwgeSA9IGF2Z195aWVsZCwgZ3JvdXAgPSBzaXRlKSkgKwogICAgZ2VvbV9saW5lKCkgKwogICAgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbCA9IHNpdGUpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBiYXJsZXlfc2l0ZV95ZWFyXzE5MzIsCiAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAibGVmdCIsIGRpcmVjdGlvbiA9ICJ5IikgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBleHBhbmRfc2NhbGUobXVsdCA9IGMoMC4xLCAuMjUpKSwKICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAidG9wIikgKwogICAgbGFicyh4ID0gTlVMTCwgeSA9ICJBdmVyYWdlIFlpZWxkIikKYGBgCgpUaGUgYW5vbWFsb3VzIHJlc3VsdCBmb3IgTW9ycmlzIHBvcHMgb3V0IHZlcnkgY2xlYXJseS4KClRoaXMgZ3JhcGggZGVwYXJ0cyBmcm9tIHRoZSBjbGFzc2ljIFR1ZnRlIHN0eWxlOgoKKiBpdCB1c2VzIGFuIGF4aXMgaW5zdGVhZCBvZiBzaG93aW5nIHRoZSBudW1iZXJzOwoqIG9ubHkgc2hvdyBsYWJlbHMgb24gb25lIHNpZGUuCgpUaGlzIGlzIHNpbWlsYXIgdG8gdGhlIHN0eWxlIHVzZWQKW2hlcmVdKGh0dHBzOi8vc2VyaWFsbWVudG9yLmNvbS9kYXRhdml6L3Zpc3VhbGl6aW5nLWFzc29jaWF0aW9ucy5odG1sI2Fzc29jaWF0aW9ucy1wYWlyZWQtZGF0YSkuCgoKIyMjIyBDcmVhdGluZyB0aGUgR3JhcGgKClRoZSBmaXJzdCBzdGVwIGlzIHRvIGNvbXB1dGUgdGhlIGF2ZXJhZ2VzOgoKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0KZXZhbF9ob3d0byA8LSBGQUxTRQpgYGAKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KYmFybGV5X3NpdGVfeWVhciA8LSBncm91cF9ieShiYXJsZXksIHNpdGUsIHllYXIpICU+JQogICAgc3VtbWFyaXplKGF2Z195aWVsZCA9IG1lYW4oeWllbGQpKQpoZWFkKGJhcmxleV9zaXRlX3llYXIsIDIpCmBgYAoKVGhlIGB5ZWFyYCB2YXJpYWJsZSBpcyBhIGZhY3RvciB3aXRoIHRoZSBsZXZlbHMgaW4gdGhlIHdyb25nIG9yZGVyLCBzbwp3ZSBuZWVkIHRvIGZpeCB0aGF0OgoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KbGV2ZWxzKGJhcmxleV9zaXRlX3llYXIkeWVhcikKYmFybGV5X3NpdGVfeWVhciA8LSBtdXRhdGUoYmFybGV5X3NpdGVfeWVhciwgeWVhciA9IGZjdF9yZXYoeWVhcikpCmxldmVscyhiYXJsZXlfc2l0ZV95ZWFyJHllYXIpCmBgYAoKU2V0IHRoZSBkZWZhdWx0IHRoZW1lIHRvIGB0aGVtZV9taW5pbWFsYCB3aXRoIGxhcmdlciB0ZXh0OgoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSArIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkpCmBgYAoKVGhlIGNvcmUgb2YgYSBzbG9wZSBncmFwaCBpcyBwcm9kdWNlZCBieQoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KcCA8LSBnZ3Bsb3QoYmFybGV5X3NpdGVfeWVhciwgYWVzKHggPSB5ZWFyLCB5ID0gYXZnX3lpZWxkLCBncm91cCA9IHNpdGUpKSArCiAgICBnZW9tX2xpbmUoKQpwCmBgYAoKQWRkaW5nIHRoZSBsYWJlbHMgb24gdGhlIDE5MzIgc2lkZSBjYW4gYmUgZG9uZSBhcwoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KYmFybGV5X3NpdGVfeWVhcl8xOTMyIDwtIGZpbHRlcihiYXJsZXlfc2l0ZV95ZWFyLCB5ZWFyID09ICIxOTMyIikKcCArIGdlb21fdGV4dChhZXMobGFiZWwgPSBzaXRlKSwKICAgICAgICAgICAgICBkYXRhID0gYmFybGV5X3NpdGVfeWVhcl8xOTMyLAogICAgICAgICAgICAgIGhqdXN0ID0gImxlZnQiKQpgYGAKClRoZSBsYWJlbCBwb3NpdGlvbnMgY291bGQgdXNlIGZ1cnRoZXIgYWRqdXN0aW5nLgoKVXNpbmcgYGdlb21fdGV4dF9yZXBlbGAgZnJvbSB0aGUgYGdncmVwZWxgIHBhY2thZ2UgaGFuZGxlcyB0aGlzIHdlbGw6CgpgYGB7ciwgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBldmFsX2hvd3RvfQpsaWJyYXJ5KGdncmVwZWwpCnAgPC0gcCArIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBzaXRlKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBiYXJsZXlfc2l0ZV95ZWFyXzE5MzIsCiAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9ICJsZWZ0IiwgZGlyZWN0aW9uID0gInkiKQpwCmBgYAoKQWRqdXN0IHRoZSBgeGAgc2NhbGU6CgpgYGB7ciwgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBldmFsX2hvd3RvfQpwIDwtIHAgKyBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGV4cGFuZF9zY2FsZShtdWx0ID0gYygwLjEsIC4yNSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gInRvcCIpCnAKYGBgCgpGaW5hbCB0aGVtZSBhZGp1c3RtZW50czoKCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IGV2YWxfaG93dG99CnAgKyBsYWJzKHggPSBOVUxMLCB5ID0gIkF2ZXJhZ2UgWWllbGQiKQpgYGAKCgojIyMgRmF0aGVyLVNvbiBIZWlnaHRzCgpUaGUgYGZhdGhlci5zb25gIGRhdGEgc2V0IGhhcyBgciBucm93KGZhdGhlci5zb24pYCBvYnNlcnZhdGlvbnMsIHdoaWNoCmlzIHRvbyBsYXJnZSBmb3IgdGhlIGxhYmVsZWQgc2xvcGUgZ3JhcGgsIGJ1dCB0aGUgYmFzaWMgcmVwcmVzZW50YXRpb24KaXMgdXNlZnVsOgoKYGBge3J9CmZzIDwtIG11dGF0ZShmYXRoZXIuc29uLCBpZCA9IHNlcV9sZW4obnJvdyhmYXRoZXIuc29uKSkpICU+JQogICAgcGl2b3RfbG9uZ2VyKDE6MiwgbmFtZXNfdG8gPSAid2hpY2giLCB2YWx1ZXNfdG8gPSAiaGVpZ2h0IikKZ2dwbG90KGZzLCBhZXMoeCA9IHdoaWNoLCB5ID0gaGVpZ2h0KSkgKwogICAgZ2VvbV9saW5lKGFlcyhncm91cCA9IGlkKSwgYWxwaGEgPSAwLjEpICsKICAgIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gZXhwYW5kX3NjYWxlKG11bHQgPSBjKC4xLCAuMSkpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJGYXRoZXIiLCAiU29uIiksCiAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gInRvcCIpICsKICAgIGxhYnMoeCA9IE5VTEwsIHkgPSAiSGVpZ2h0IChJbmNoZXMpIikKYGBgCgpUaGlzIHZlcnkgY2xlYXJseSBzaG93cyB0aGUgZmFtb3VzIF9yZWdyZXNzaW9uIHRvIHRoZSBtZWFuXyBlZmZlY3Q6CgoqIHRhbGxlciBwYXJlbnRzIHRlbmQgdG8gYmUgdGFsbGVyIHRoYW4gdGhlaXIgY2hpbGRyZW47Ciogc2hvcnRlciBwYXJlbnRzIHRlbmQgdG8gYmUgc2hvcnRlciB0aGFuIHRoZWlyIGNoaWxkcmVuLgoKQ29udmVyc2VseSwKCiogdGFsbGVyIGNoaWxkcmVuIHRlbmQgdG8gYmUgdGFsbGVyIHRoYW4gdGhlaXIgcGFyZW50czsKKiBzaG9ydGVyIGNoaWxkcmVuIHRlbmQgdG8gYmUgc2hvcnRlciB0aGFuIHRoZWlyIHBhcmVudHMuCgo8IS0tCmZzIDwtIG11dGF0ZShmcywgVG9yU0YgPSBhYnMoaGVpZ2h0IC0gbWVhbihoZWlnaHQpKSA+IDEuNSAqIHNkKGhlaWdodCkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWNoID09ICJmaGVpZ2h0IikKZ2dwbG90KGZzKSArCmdlb21fbGluZShhZXMoeCA9IHdoaWNoLCB5ID0gaGVpZ2h0LCBncm91cCA9IGlkLCBjb2xvciA9IFRvclNGKSwgYWxwaGEgPSAwLjEpICsKc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKC4xLCAwKSkgKwpzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVFJVRSIgPSAicmVkIiwgIkZBTFNFIiA9ICJibGFjayIpKQotLT4KCgojIyMjIENyZWF0aW5nIHRoZSBHcmFwaAoKVG8gbWFrZSBjcmVhdGluZyB0aGUgZ3JhcGggZWFzaWVyIHdlIGNhbiBjb252ZXJ0IHRoZSBkYXRhIGZyYW1lIGludG8KYSBsb25nZXIgZm9ybSB3aXRoIHZhcmlhYmxlcwoKKiBgaGVpZ2h0YCwgdGhlIGhlaWdodCBtZWFzdXJlbWVudAoqIGB3aGljaGAsIGBmaGVpZ2h0YCBvciBgc2hlaWdodGAKKiBgaWRgLCBpZGVudGlmeWluZyB0aGUgcGFpcjoKCkFkZCB0aGUgYGlkYCB2YXJpYWJsZToKICAgIApgYGB7ciwgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBldmFsX2hvd3RvfQpmcyA8LSBtdXRhdGUoZmF0aGVyLnNvbiwgaWQgPSBzZXFfbGVuKG5yb3coZmF0aGVyLnNvbikpKQpoZWFkKGZzKQpgYGAKClBpdm90IHRvIHRoZSBsb25nZXIgZm9ybWF0OgoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KZnMgPC0gcGl2b3RfbG9uZ2VyKGZzLCAxOjIsIG5hbWVzX3RvID0gIndoaWNoIiwgdmFsdWVzX3RvID0gImhlaWdodCIpCmhlYWQoZnMpCmBgYAoKVGhlIGJhc2ljIHBsb3QgaXMgcXVpdGUgc2ltcGxlOgoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KZ2dwbG90KGZzLCBhZXMoeCA9IHdoaWNoLCB5ID0gaGVpZ2h0LCBncm91cCA9IGlkKSkgKyBnZW9tX2xpbmUoKQpgYGAKCldpdGggYW4gYGFscGhhYCBhZGp1c3RtZW50IHRvIHJlZHVjZSBvdmVyLXBsb3R0aW5nOgoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gZXZhbF9ob3d0b30KcCA8LSBnZ3Bsb3QoZnMsIGFlcyh4ID0gd2hpY2gsIHkgPSBoZWlnaHQsIGdyb3VwID0gaWQpKSArCiAgICBnZW9tX2xpbmUoYWxwaGEgPSAwLjEpCnAKYGBgCgpXaXRoIGFuIGF4aXMgYWRqdXN0bWVudCBhbmQgdXNpbmcgYSByZWR1Y2VkIGBhbHBoYWAgbGV2ZWw6CgpgYGB7ciwgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBldmFsX2hvd3RvfQpwICsgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBleHBhbmRfc2NhbGUobXVsdCA9IGMoLjEsIC4xKSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkZhdGhlciIsICJTb24iKSwKICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAidG9wIikgKwogICAgbGFicyh4ID0gTlVMTCwgeSA9ICJIZWlnaHQgKEluY2hlcykiKQpgYGAKCgojIyBTY2F0dGVyIFBsb3RzCgpBIHNjYXR0ZXIgcGxvdCBvZiB0d28gdmFyaWFibGVzIG1hcHMgdGhlIHZhbHVlcyBvZiBvbmUgdmFyaWFibGUKdG8gdGhlIHZlcnRpY2FsIGF4aXMgYW5kIHRoZSBvdGhlciB0byB0aGUgaG9yaXpvbnRhbCBheGlzIG9mIGEKY2FydGVzaWFuIGNvb3JkaW5hdGUgc3lzdGVtIGFuZCBwbGFjZXMgYSBtYXJrIGZvciBlYWNoIG9ic2VydmF0aW9uCmF0IHRoZSByZXN1bHRpbmcgcG9pbnQuCgpDb252ZW50aW9uczoKCiogUGxvdCBgQWAgdmVyc3VzL2FnYWluc3QgYEJgIG1lYW5zIGBBYCBpcyBtYXBwZWQgdG8gdGhlIHZlcnRpY2FsLCBvcgogICR5JCwgYXhpcywgYW5kIGBCYCB0byB0aGUgaG9yaXpvbnRhbCwgb3IgJHgkIGF4aXMuCgoqIElmIHdlIGNhbiB0aGluayBvZiB2YXJpYXRpb24gaW4gYEFgIGFzIGJlaW5nIHBhcnRseSBleHBsYWluZWQgYnkgYEJgCiAgdGhlbiB3ZSB1c3VhbGx5IHBsb3QgYEFgIGFnYWluc3QgYEJgLgoKKiBJZiB3ZSBjYW4gdGhpbmsgb2YgYEJgIGFzIGhlbHBpbmcgdG8gcHJlZGljdCBgQWAsIHRoZW4gd2UgdXN1YWxseQogIHBsb3QgYEFgIGFnYWluc3QgYEJgLgoKCiMjIyBCYXJsZXkgWWllbGRzCgpGb3IgYSBzY2F0dGVyIHBsb3Qgb2YgbWVhbiB5aWVsZCBpbiAxOTMyIGFnYWluc3QgbWVhbiB5aWVsZCBpbiAxOTMxCmZvciB0aGUgZGlmZmVyZW50IHNpdGVzIGl0IGlzIHVzZWZ1bCB0byBoYXZlIGEgZGF0YSBmcmFtZSBjb250YWluaW5nCnZhcmlhYmxlcyBmb3IgZWFjaCB5ZWFyLgoKVGhpcyByZXF1aXJlcyBjb252ZXJ0aW5nIHRoZSBkYXRhIGZyYW1lIHRvIGEgd2lkZXIgZm9ybWF0LgoKYGBge3J9CndpZGVfYmFybGV5X3NpdGVfeWVhciA8LSBwaXZvdF93aWRlcihiYXJsZXlfc2l0ZV95ZWFyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9ICJ5ZWFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3ByZWZpeCA9ICJhdmdfeWllbGRfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gImF2Z195aWVsZCIpCmhlYWQod2lkZV9iYXJsZXlfc2l0ZV95ZWFyKQpgYGAKClRoZSBiYXNpYyBzY2F0dGVyIHBsb3Qgb2YgYHkgPSBhdmdfeWllbGRfMTkzMmAgYWdhaW5zdCBgeCA9CmF2Z195aWVsZF95ZWFyMTkzMWA6CgpgYGB7cn0KcCA8LSBnZ3Bsb3Qod2lkZV9iYXJsZXlfc2l0ZV95ZWFyLAogICAgICAgICAgICBhZXMoeCA9IGF2Z195aWVsZF8xOTMxLCB5ID0gYXZnX3lpZWxkXzE5MzIpKSArCiAgICBnZW9tX3BvaW50KCkKcApgYGAKCkFkZGluZyBsYWJlbHMgdXNpbmcgYGdlb21fdGV4dF9yZXBlbGAgaWRlbnRpZmllcyB0aGUgTW9ycmlzIHNpdGU6CgpgYGB7cn0KcCA8LSBwICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbCA9IHNpdGUpLCB2anVzdCA9ICJ0b3AiKQpwCmBgYAoKVG8gcmVjb2duaXplIHRoZSByZXZlcnNhbCBmb3IgTW9ycmlzIHdlIGNhbiBhZGQgdGhlIDQ1IGRlZ3JlZSBsaW5lOgoKYGBge3J9CnAgKyBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSwgbGluZXR5cGUgPSAyKQpgYGAKCkEgNDUgZGVncmVlIGxpbmUgYWxzbyBoZWxwcyB3aGVuIHZpZXdpbmcgdGhlIGZ1bGwgZGF0YToKICAKYGBge3J9CmJ3IDwtIHBpdm90X3dpZGVyKGJhcmxleSwKICAgICAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9ICJ5ZWFyIiwgbmFtZXNfcHJlZml4ID0gInlpZWxkXyIsCiAgICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gInlpZWxkIikKZ2dwbG90KGJ3LCBhZXMoeCA9IHlpZWxkXzE5MzEsIHkgPSB5aWVsZF8xOTMyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAyKSArCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoYncsIHNpdGUgPT0gIk1vcnJpcyIpLCBjb2xvciA9ICJyZWQiKSArCiAgICBnZ3RpdGxlKCJCYXJsZXkgWWllbGRzIiwgIlZhbHVlcyBmb3IgTW9ycmlzIGFyZSBzaG93biBpbiByZWQuIikgKwogICAgbGFicyh4ID0gIjE5MzEiLCB5ID0gIjE5MzIiKQpgYGAKCkEgcmVjZW50IFtibG9nCnBvc3RdKGh0dHBzOi8vZWFnZXJleWVzLm9yZy9ibG9nLzIwMjAvaW4tcHJhaXNlLW9mLXRoZS1kaWFnb25hbC1yZWZlcmVuY2UtbGluZSkKZGlzY3Vzc2VzIHRoZSB2YWx1ZSBvZiByZWZlcmVuY2UgbGluZXMgYXMgcGxvdCBhbm5vdGF0aW9ucy4KCklmIHRoZSBwcmltYXJ5IGdvYWwgaXMgdG8gc2hvdyB0aGUgY2hhbmdlIGZyb20gb25lIHllYXIgdG8gdGhlIG5leHQKdGhlbiBhIG1lYW4tZGlmZmVyZW5jZSBwbG90IGlzIGEgZ29vZCBjaG9pY2U6CiAgCmBgYHtyfQpnZ3Bsb3Qod2lkZV9iYXJsZXlfc2l0ZV95ZWFyLAogICAgICAgYWVzKHggPSAoYXZnX3lpZWxkXzE5MzIgKyBhdmdfeWllbGRfMTkzMSkgLyAyLAogICAgICAgICAgIHkgPSBhdmdfeWllbGRfMTkzMiAtIGF2Z195aWVsZF8xOTMxKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBzaXRlKSwgdmp1c3QgPSAidG9wIikgKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMCksIGxpbmV0eXBlID0gMikKYGBgCgpGb3IgdGhlIGZ1bGwgZGF0YToKICAgIApgYGB7cn0KZ2dwbG90KGJ3LAogICAgICAgYWVzKHggPSAoeWllbGRfMTkzMiArIHlpZWxkXzE5MzEpIC8gMiwKICAgICAgICAgICB5ID0geWllbGRfMTkzMiAtIHlpZWxkXzE5MzEpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMCksIGxpbmV0eXBlID0gMikKYGBgCgpUaGUgY29tcGFyaXNvbiBvZiBjaGFuZ2VzIGlzIG5vdyBhbiBhbGlnbmVkIGF4aXMgY29tcGFyaXNvbi4KCk1lYW4tZGlmZmVyZW5jZSBwbG90cyBhcmUgYWxzbyBrbm93biBhcwoKKiBUdWtleSBtZWFuLWRpZmZlcmVuY2UgcGxvdHM7CiogTUEtcGxvdHM7CiogW0JsYW5kLUFsdG1hbiBwbG90c10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmxhbmQlRTIlODAlOTNBbHRtYW5fcGxvdCkuCgpQbG90dGluZyB0aGUgZGlmZmVyZW5jZSBhZ2FpbnN0IHRoZSBgeGAgdmFyaWFibGUgaXMgYWxzbyBvZnRlbiB1c2VmdWw6CgpgYGB7cn0KZ2dwbG90KGJ3LAogICAgICAgYWVzKHggPSB5aWVsZF8xOTMxLAogICAgICAgICAgIHkgPSB5aWVsZF8xOTMyIC0geWllbGRfMTkzMSkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoYncsIHNpdGUgPT0gIk1vcnJpcyIpLCBjb2xvciA9ICJyZWQiKSArCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAwKSwgbGluZXR5cGUgPSAyKSArCiAgICBnZ3RpdGxlKCJCYXJsZXkgWWllbGQgRGlmZmVyZW5jZXMiLCAiVmFsdWVzIGZvciBNb3JyaXMgYXJlIHNob3duIGluIHJlZC4iKSArCiAgICBsYWJzKHggPSAiWWllbGQgaW4gMTkzMSIsIHkgPSAiRGlmZmVyZW5jZSBpbiBZaWVsZCBmb3IgMTkzMiIpCmBgYAoKCiMjIyBGYXRoZXIgYW5kIFNvbiBIZWlnaHRzCgpUaGUgYmFzaWMgc2NhdHRlciBwbG90OgoKYGBge3J9CnAwIDwtICBnZ3Bsb3QoZmF0aGVyLnNvbiwgYWVzKHggPSBmaGVpZ2h0LCB5ID0gc2hlaWdodCkpCnAxIDwtIHAwICsgZ2VvbV9wb2ludCgpCnAxCmBgYAoKQWRkaW5nIGEgbGluZSB3aXRoIHNsb3BlIG9uZSBoZWxwcyBpZGVudGlmeSB0aGUgcmVncmVzc2lvbiB0byB0aGUgbWVhbgpwaGVub21lbm9uOgoKCmBgYHtyfQpwMiA8LSBwMSArIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBtZWFuKHNoZWlnaHQpIC0gbWVhbihmaGVpZ2h0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvcGUgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBzaXplID0gMS41KQpwMgpgYGAKCkFkZGluZyBhIHJlZ3Jlc3Npb24gbGluZSBoZWxwcyBmdXJ0aGVyOgoKYGBge3J9CnAyICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikKCmBgYAoKQnV0IGZvciBzaG93aW5nIHRoZSByZWdyZXNzaW9uIGVmZmVjdCBpdCBpcyBoYXJkIHRvIGJlYXQgdGhlIHNjYXR0ZXIKcGxvdCBvZiBgc2hlaWdodCAtIGZoZWlnaHRgIGFnYWluc3QgYGZoZWlnaHRgOgoKYGBge3J9CmdncGxvdChmYXRoZXIuc29uKSArCiAgICBnZW9tX3BvaW50KGFlcyh4ID0gZmhlaWdodCwgeSA9IHNoZWlnaHQgLSBmaGVpZ2h0KSkgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApLCBsaW5ldHlwZSA9IDIpCmBgYAoKCiMjIyBPbGQgRmFpdGhmdWwgRXJ1cHRpb25zCgpBIHNjYXR0ZXIgcGxvdCBvZiB0aGUgd2FpdGluZyB0aW1lcyB1bnRpbCB0aGUgbmV4dCBlcnVwdGlvbiBhZ2FpbnN0CnRoZSBkdXJhdGlvbiBvZiB0aGUgY3VycmVudCBlcnVwdGlvbiBmb3IgdGhlIGBmYWl0aGZ1bGAgZGF0YSBzZXQgc2hvd3MKdGhlIHR3byBjbHVzdGVycyBjb3JyZXNwb25kaW5nIHRvIHRoZSBzaG9ydCBhbmQgbG9uZyBlcnVwdGlvbnM6CgpgYGB7cn0KZ2dwbG90KGZhaXRoZnVsKSArIGdlb21fcG9pbnQoYWVzKHggPSBlcnVwdGlvbnMsIHkgPSB3YWl0aW5nKSkKYGBgCgpGb3IgdGhlIGBnZXlzZXJgIGRhdGEgc2V0IGZyb20gdGhlIGBNQVNTYCBwYWNrYWdlIGEgcGxvdCBvZiB0aGUgdHdvCnZhcmlhYmxlcyBzaG93cyBhIGRpZmZlcmVudCBwYXR0ZXJuOgoKYGBge3J9CmdncGxvdChnZXlzZXIpICsgZ2VvbV9wb2ludChhZXMoeCA9IGR1cmF0aW9uLCB5ID0gd2FpdGluZykpCmBgYAoKVGhlIHJlYXNvbiBmb3IgdGhlIGRpZmZlcmVuY2UgaXMgdGhhdCBpbiB0aGUgYGdleXNlcmAgZGF0YSBzZXQgdGhlCndhaXRpbmcgdGltZSByZWZsZWN0cyB0aGUgdGltZSBzaW5jZSB0aGUgX3ByZXZpb3VzXyBlcnVwdGlvbiwgbm90IHRoZQp0aW1lIHVudGlsIHRoZSBfbmV4dF8gb25lLgoKRm9yIHRoaXMgb3JkZXJpbmcgaXQgaXMgbW9yZSBuYXR1cmFsIHRvIHBsb3QgYGR1cmF0aW9uYCBhZ2FpbnN0IGB3YWl0aW5nYDoKCmBgYHtyfQpnZ3Bsb3QoZ2V5c2VyKSArIGdlb21fcG9pbnQoYWVzKHggPSB3YWl0aW5nLCB5ID0gZHVyYXRpb24pKQpgYGAKCkhvdyB3ZWxsIGRvZXMgdGhlIHdhaXRpbmcgdGltZSBwcmVkaWN0IHdoZXRoZXIgdGhlIGR1cmF0aW9uIHdpbGwgYmUKbG9uZ2VyIG9yIHNob3J0ZXI/CgpUaGUgcXVlc3Rpb24gdGhlIHBhcmsgc2VydmljZSBpcyBtb3JlIGludGVyZXN0ZWQgaW4gaXMgaG93IHdlbGwKZHVyYXRpb24gcHJlZGljdCB3YWl0aW5nIHRpbWUgdW50aWwgdGhlIG5leHQgZXJ1cHRpb24uCgpXZSBjYW4gYWRqdXN0IHRoZXNlIGRhdGEgdG8gcGFpciBkdXJhdGlvbnMgd2l0aCB3YWl0aW5nIHRpbWVzIHVudGlsCnRoZSBuZXh0IGVydXB0aW9uIHVzaW5nIHRoZSBgbGFnYCBmdW5jdGlvbiBmcm9tIGBkcGx5cmAuIFRoaXMgcHJvZHVjZXMKdGhlIHNhbWUgYmFzaWMgcGF0dGVybiBhcyBmb3IgdGhlIGBmYWl0aGZ1bGAgZGF0YSBzZXQ6CgpgYGB7cn0KZ2dwbG90KGdleXNlcikgKyBnZW9tX3BvaW50KGFlcyh4ID0gbGFnKGR1cmF0aW9uKSwgeSA9IHdhaXRpbmcpKQpgYGAKCjwhLS0KTG9jYWwgVmFyaWFibGVzOiAKbW9kZTogcG9seS1tYXJrZG93bitSCm1vZGU6IGZseXNwZWxsCkVuZDoKLS0+Cg== Which chart displays the relationship between two numeric variables?A scatterplot is a type of data display that shows the relationship between two numerical variables. Each member of the dataset gets plotted as a point whose x-y coordinates relates to its values for the two variables.
What graph do you use for two numerical variables?Scatter plots are used when you want to show the relationship between two variables. A scatter chart works best when comparing large numbers of data points without regard to time. Often, scatter plots will include a trend line to help make the relationship more clear.
|