4.2 - Using the Gapminder Dataset
Faceting
🎞 Faceting
📖 Faceting
- Faceting makes multiple side-by-side plots stratified by some variable. This is a way to ease comparisons.
- The
facet_grid() function allows faceting by up to two variables, with rows faceted by one variable and columns faceted by the other variable. To facet by only one variable, use the dot operator as the other variable.
- The
facet_wrap() function facets by one variable and automatically wraps the series of plots so they have readable dimensions.
- Faceting keeps the axes fixed across all plots, easing comparisons between plots.
- The data suggest that the developing versus Western world view no longer makes sense in 2012.
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(dslabs)
library(ggplot2)
data(gapminder)
# Facet by continent and year
filter(gapminder, year %in% c(1962, 2012)) %>%
ggplot(aes(fertility, life_expectancy, col=continent)) +
geom_point() +
facet_grid(continent~year)

# Facet by year only
filter(gapminder, year %in% c(1962, 1980, 2012)) %>%
ggplot(aes(fertility, life_expectancy, col=continent)) +
geom_point() +
facet_grid(.~year)

# Facet by year, plots wrapped onto multiple rows
years <- c(1962, 1980, 1990, 2000, 2012)
continents <- c("Europe", "Asia")
gapminder %>%
filter(year %in% years & continent %in% continents) %>%
ggplot(aes(fertility, life_expectancy, col=continent)) +
geom_point() +
facet_wrap(~year)

Time Series Plots
🎞 Time Series Plots
📖 Time series plots
- Time series plots have time on the x-axis and a variable of interest on the y-axis.
- The
geom_line() geometry connects adjacent data points to form a continuous line. A line plot is appropriate when points are regularly spaced, densely packed and from a single data series.
- You can plot multiple lines on the same graph. Remember to group or color by a variable so that the lines are plotted independently.
- Labeling is usually preferred over legends. However, legends are easier to make and appear by default. Add a label with
geom_text(), specifying the coordinates where the label should appear on the graph.
Code: Single time series
# Scatterplot of US fertility by year
gapminder %>%
filter(country=="United States") %>%
ggplot(aes(year, fertility)) +
geom_point()

# Line plot of US fertility by year
gapminder %>%
filter(country=="United States") %>%
ggplot(aes(year, fertility)) +
geom_line()

Code: Multiple time series
# Line plot fertility time series for two countries- only one line (incorrect)
countries <- c("South Korea", "Germany")
gapminder %>% filter(country %in% countries) %>%
ggplot(aes(year, fertility)) +
geom_line()

# Line plot fertility time series for two countries - one line per country
gapminder %>% filter(country %in% countries) %>%
ggplot(aes(year, fertility, group=country)) +
geom_line()

# Fertility time series for two countries - lines colored by country
gapminder %>% filter(country %in% countries) %>%
ggplot(aes(year, fertility, col=country)) +
geom_line()

Code: Adding text labels to a plot
# Life expectancy time series - lines colored by country and labeled, no legend
labels <- data.frame(country=countries, x=c(1975, 1965), y=c(60, 72))
gapminder %>% filter(country %in% countries) %>%
ggplot(aes(year, life_expectancy, col=country)) +
geom_line() +
geom_text(data=labels, aes(x, y, label=country), size=5) +
theme(legend.position="none")

LS0tCnRpdGxlOiAiQ291cnNlIDIgLSBEYXRhIFNjaWVuY2U6IFZpc3VhbGl6YXRpb24iCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIHRoZW1lOiBmbGF0bHkKLS0tCgojIyA0LjIgLSBVc2luZyB0aGUgR2FwbWluZGVyIERhdGFzZXQKCl9fXyAKIyMjIyAqKkZhY2V0aW5nKioKCj4g8J+OniBbRmFjZXRpbmddKGh0dHBzOi8vZWR4LXZpZGVvLm5ldC9IQVJCMDIwRDIwMTctVjAwMjUwMF9EVEgubXA0KQo+IAo+IPCfk5YgW0ZhY2V0aW5nXShodHRwczovL3JhZmFsYWIuZ2l0aHViLmlvL2RzYm9vay9nYXBtaW5kZXIuaHRtbCNmYWNldGluZykKCi0gRmFjZXRpbmcgbWFrZXMgbXVsdGlwbGUgc2lkZS1ieS1zaWRlIHBsb3RzIHN0cmF0aWZpZWQgYnkgc29tZSB2YXJpYWJsZS4gVGhpcyBpcyBhIHdheSB0byBlYXNlIGNvbXBhcmlzb25zLgotIFRoZSBgZmFjZXRfZ3JpZCgpYCBmdW5jdGlvbiBhbGxvd3MgZmFjZXRpbmcgYnkgdXAgdG8gdHdvIHZhcmlhYmxlcywgd2l0aCByb3dzIGZhY2V0ZWQgYnkgb25lIHZhcmlhYmxlIGFuZCBjb2x1bW5zIGZhY2V0ZWQgYnkgdGhlIG90aGVyIHZhcmlhYmxlLiBUbyBmYWNldCBieSBvbmx5IG9uZSB2YXJpYWJsZSwgdXNlIHRoZSAqZG90IG9wZXJhdG9yKiBhcyB0aGUgb3RoZXIgdmFyaWFibGUuCi0gVGhlIGBmYWNldF93cmFwKClgIGZ1bmN0aW9uIGZhY2V0cyBieSBvbmUgdmFyaWFibGUgYW5kIGF1dG9tYXRpY2FsbHkgd3JhcHMgdGhlIHNlcmllcyBvZiBwbG90cyBzbyB0aGV5IGhhdmUgcmVhZGFibGUgZGltZW5zaW9ucy4KLSBGYWNldGluZyBrZWVwcyB0aGUgYXhlcyBmaXhlZCBhY3Jvc3MgYWxsIHBsb3RzLCBlYXNpbmcgY29tcGFyaXNvbnMgYmV0d2VlbiBwbG90cy4KLSBUaGUgZGF0YSBzdWdnZXN0IHRoYXQgdGhlIGRldmVsb3BpbmcgdmVyc3VzIFdlc3Rlcm4gd29ybGQgdmlldyBubyBsb25nZXIgbWFrZXMgc2Vuc2UgaW4gMjAxMi4KYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZHNsYWJzKQpsaWJyYXJ5KGdncGxvdDIpCmRhdGEoZ2FwbWluZGVyKQojIEZhY2V0IGJ5IGNvbnRpbmVudCBhbmQgeWVhcgpmaWx0ZXIoZ2FwbWluZGVyLCB5ZWFyICVpbiUgYygxOTYyLCAyMDEyKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKGZlcnRpbGl0eSwgbGlmZV9leHBlY3RhbmN5LCBjb2w9Y29udGluZW50KSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGZhY2V0X2dyaWQoY29udGluZW50fnllYXIpCiMgRmFjZXQgYnkgeWVhciBvbmx5CmZpbHRlcihnYXBtaW5kZXIsIHllYXIgJWluJSBjKDE5NjIsIDE5ODAsIDIwMTIpKSAlPiUKICAgIGdncGxvdChhZXMoZmVydGlsaXR5LCBsaWZlX2V4cGVjdGFuY3ksIGNvbD1jb250aW5lbnQpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgZmFjZXRfZ3JpZCgufnllYXIpCiMgRmFjZXQgYnkgeWVhciwgcGxvdHMgd3JhcHBlZCBvbnRvIG11bHRpcGxlIHJvd3MKeWVhcnMgPC0gYygxOTYyLCAxOTgwLCAxOTkwLCAyMDAwLCAyMDEyKQpjb250aW5lbnRzIDwtIGMoIkV1cm9wZSIsICJBc2lhIikKZ2FwbWluZGVyICU+JQogICAgZmlsdGVyKHllYXIgJWluJSB5ZWFycyAmIGNvbnRpbmVudCAlaW4lIGNvbnRpbmVudHMpICU+JQogICAgZ2dwbG90KGFlcyhmZXJ0aWxpdHksIGxpZmVfZXhwZWN0YW5jeSwgY29sPWNvbnRpbmVudCkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBmYWNldF93cmFwKH55ZWFyKQpgYGAKX19fIAojIyMjICoqVGltZSBTZXJpZXMgUGxvdHMqKgoKPiDwn46eIFtUaW1lIFNlcmllcyBQbG90c10oaHR0cHM6Ly9lZHgtdmlkZW8ubmV0L0hBUkIwMjBEMjAxNy1WMDAyOTAwX0RUSC5tcDQpCj4gCj4g8J+TliBbVGltZSBzZXJpZXMgcGxvdHNdKGh0dHBzOi8vcmFmYWxhYi5naXRodWIuaW8vZHNib29rL2dhcG1pbmRlci5odG1sI3RpbWUtc2VyaWVzLXBsb3RzKQoKLSBUaW1lIHNlcmllcyBwbG90cyBoYXZlIHRpbWUgb24gdGhlIHgtYXhpcyBhbmQgYSB2YXJpYWJsZSBvZiBpbnRlcmVzdCBvbiB0aGUgeS1heGlzLgotIFRoZSBgZ2VvbV9saW5lKClgIGdlb21ldHJ5IGNvbm5lY3RzIGFkamFjZW50IGRhdGEgcG9pbnRzIHRvIGZvcm0gYSBjb250aW51b3VzIGxpbmUuIEEgbGluZSBwbG90IGlzIGFwcHJvcHJpYXRlIHdoZW4gcG9pbnRzIGFyZSByZWd1bGFybHkgc3BhY2VkLCBkZW5zZWx5IHBhY2tlZCBhbmQgZnJvbSBhIHNpbmdsZSBkYXRhIHNlcmllcy4KLSBZb3UgY2FuIHBsb3QgbXVsdGlwbGUgbGluZXMgb24gdGhlIHNhbWUgZ3JhcGguIFJlbWVtYmVyIHRvIGdyb3VwIG9yIGNvbG9yIGJ5IGEgdmFyaWFibGUgc28gdGhhdCB0aGUgbGluZXMgYXJlIHBsb3R0ZWQgaW5kZXBlbmRlbnRseS4KLSBMYWJlbGluZyBpcyB1c3VhbGx5IHByZWZlcnJlZCBvdmVyIGxlZ2VuZHMuIEhvd2V2ZXIsIGxlZ2VuZHMgYXJlIGVhc2llciB0byBtYWtlIGFuZCBhcHBlYXIgYnkgZGVmYXVsdC4gQWRkIGEgbGFiZWwgd2l0aCBgZ2VvbV90ZXh0KClgLCBzcGVjaWZ5aW5nIHRoZSBjb29yZGluYXRlcyB3aGVyZSB0aGUgbGFiZWwgc2hvdWxkIGFwcGVhciBvbiB0aGUgZ3JhcGguCgpDb2RlOiBTaW5nbGUgdGltZSBzZXJpZXMKYGBge3J9CiMgU2NhdHRlcnBsb3Qgb2YgVVMgZmVydGlsaXR5IGJ5IHllYXIKZ2FwbWluZGVyICU+JQogICAgZmlsdGVyKGNvdW50cnk9PSJVbml0ZWQgU3RhdGVzIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHllYXIsIGZlcnRpbGl0eSkpICsKICAgIGdlb21fcG9pbnQoKQojIExpbmUgcGxvdCBvZiBVUyBmZXJ0aWxpdHkgYnkgeWVhcgpnYXBtaW5kZXIgJT4lCiAgICBmaWx0ZXIoY291bnRyeT09IlVuaXRlZCBTdGF0ZXMiKSAlPiUKICAgIGdncGxvdChhZXMoeWVhciwgZmVydGlsaXR5KSkgKwogICAgZ2VvbV9saW5lKCkKYGBgCkNvZGU6IE11bHRpcGxlIHRpbWUgc2VyaWVzCmBgYHtyfQojIExpbmUgcGxvdCBmZXJ0aWxpdHkgdGltZSBzZXJpZXMgZm9yIHR3byBjb3VudHJpZXMtIG9ubHkgb25lIGxpbmUgKGluY29ycmVjdCkKY291bnRyaWVzIDwtIGMoIlNvdXRoIEtvcmVhIiwgIkdlcm1hbnkiKQpnYXBtaW5kZXIgJT4lIGZpbHRlcihjb3VudHJ5ICVpbiUgY291bnRyaWVzKSAlPiUKICAgIGdncGxvdChhZXMoeWVhciwgZmVydGlsaXR5KSkgKwogICAgZ2VvbV9saW5lKCkKIyBMaW5lIHBsb3QgZmVydGlsaXR5IHRpbWUgc2VyaWVzIGZvciB0d28gY291bnRyaWVzIC0gb25lIGxpbmUgcGVyIGNvdW50cnkKZ2FwbWluZGVyICU+JSBmaWx0ZXIoY291bnRyeSAlaW4lIGNvdW50cmllcykgJT4lCiAgICBnZ3Bsb3QoYWVzKHllYXIsIGZlcnRpbGl0eSwgZ3JvdXA9Y291bnRyeSkpICsKICAgIGdlb21fbGluZSgpCiMgRmVydGlsaXR5IHRpbWUgc2VyaWVzIGZvciB0d28gY291bnRyaWVzIC0gbGluZXMgY29sb3JlZCBieSBjb3VudHJ5CmdhcG1pbmRlciAlPiUgZmlsdGVyKGNvdW50cnkgJWluJSBjb3VudHJpZXMpICU+JQogICAgZ2dwbG90KGFlcyh5ZWFyLCBmZXJ0aWxpdHksIGNvbD1jb3VudHJ5KSkgKwogICAgZ2VvbV9saW5lKCkKYGBgCkNvZGU6IEFkZGluZyB0ZXh0IGxhYmVscyB0byBhIHBsb3QKYGBge3J9CiMgTGlmZSBleHBlY3RhbmN5IHRpbWUgc2VyaWVzIC0gbGluZXMgY29sb3JlZCBieSBjb3VudHJ5IGFuZCBsYWJlbGVkLCBubyBsZWdlbmQKbGFiZWxzIDwtIGRhdGEuZnJhbWUoY291bnRyeT1jb3VudHJpZXMsIHg9YygxOTc1LCAxOTY1KSwgeT1jKDYwLCA3MikpCmdhcG1pbmRlciAlPiUgZmlsdGVyKGNvdW50cnkgJWluJSBjb3VudHJpZXMpICU+JQogICAgZ2dwbG90KGFlcyh5ZWFyLCBsaWZlX2V4cGVjdGFuY3ksIGNvbD1jb3VudHJ5KSkgKwogICAgZ2VvbV9saW5lKCkgKwogICAgZ2VvbV90ZXh0KGRhdGE9bGFiZWxzLCBhZXMoeCwgeSwgbGFiZWw9Y291bnRyeSksIHNpemU9NSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKYGBgCl9fXyAKIyMjIyAqKlRyYW5zZm9ybWF0aW9ucyoqCgo+IPCfjp4gW1RyYW5zZm9ybWF0aW9uc10oaHR0cHM6Ly9lZHgtdmlkZW8ubmV0L0hBUkIwMjBEMjAxNy1WMDAyNzAwX0RUSC5tcDQpCj4gCj4g8J+TliBbRGF0YSB0cmFuc2Zvcm1hdGlvbnNdKGh0dHBzOi8vcmFmYWxhYi5naXRodWIuaW8vZHNib29rL2dhcG1pbmRlci5odG1sI2RhdGEtdHJhbnNmb3JtYXRpb25zKQo+IAo+IPCfk5YgW1Zpc3VhbGl6aW5nIG11bHRpbW9kYWwgZGlzdHJpYnV0aW9uc10oaHR0cHM6Ly9yYWZhbGFiLmdpdGh1Yi5pby9kc2Jvb2svZ2FwbWluZGVyLmh0bWwjdmlzdWFsaXppbmctbXVsdGltb2RhbC1kaXN0cmlidXRpb25zKQoKLSBXZSB1c2UgR0RQIGRhdGEgdG8gY29tcHV0ZSBpbmNvbWUgaW4gVVMgZG9sbGFycyBwZXIgZGF5LCBhZGp1c3RlZCBmb3IgaW5mbGF0aW9uLgotIExvZyB0cmFuc2Zvcm1hdGlvbnMgY29udmVydCBtdWx0aXBsaWNhdGl2ZSBjaGFuZ2VzIGludG8gYWRkaXRpdmUgY2hhbmdlcy4KLSBDb21tb24gdHJhbnNmb3JtYXRpb25zIGFyZSB0aGUgbG9nIGJhc2UgMiB0cmFuc2Zvcm1hdGlvbiBhbmQgdGhlIGxvZyBiYXNlIDEwIHRyYW5zZm9ybWF0aW9uLiBUaGUgY2hvaWNlIG9mIGJhc2UgZGVwZW5kcyBvbiB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGEuIFRoZSBuYXR1cmFsIGxvZyBpcyBub3QgcmVjb21tZW5kZWQgZm9yIHZpc3VhbGl6YXRpb24gYmVjYXVzZSBpdCBpcyBkaWZmaWN1bHQgdG8gaW50ZXJwcmV0LgotIFRoZSBtb2RlIG9mIGEgZGlzdHJpYnV0aW9uIGlzIHRoZSB2YWx1ZSB3aXRoIHRoZSBoaWdoZXN0IGZyZXF1ZW5jeS4gVGhlIG1vZGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGlzIHRoZSBhdmVyYWdlLiBBIGRpc3RyaWJ1dGlvbiBjYW4gaGF2ZSBtdWx0aXBsZSBsb2NhbCBtb2Rlcy4KLSBUaGVyZSBhcmUgdHdvIHdheXMgdG8gdXNlIGxvZyB0cmFuc2Zvcm1hdGlvbnMgaW4gcGxvdHM6IHRyYW5zZm9ybSB0aGUgZGF0YSBiZWZvcmUgcGxvdHRpbmcgb3IgdHJhbnNmb3JtIHRoZSBheGVzIG9mIHRoZSBwbG90LiBMb2cgc2NhbGVzIGhhdmUgdGhlIGFkdmFudGFnZSBvZiBzaG93aW5nIHRoZSBvcmlnaW5hbCB2YWx1ZXMgYXMgYXhpcyBsYWJlbHMsIHdoaWxlIGxvZyB0cmFuc2Zvcm1lZCB2YWx1ZXMgZWFzZSBpbnRlcnByZXRhdGlvbiBvZiBpbnRlcm1lZGlhdGUgdmFsdWVzIGJldHdlZW4gbGFiZWxzLgotIFNjYWxlIHRoZSB4LWF4aXMgdXNpbmcgYHNjYWxlX3hfY29udGludW91cygpYCBvciBgc2NhbGVfeF9sb2cxMCgpYCBsYXllcnMgaW4gKmdncGxvdDIqLiBTaW1pbGFyIGZ1bmN0aW9ucyBleGlzdCBmb3IgdGhlIHktYXhpcy4KLSBJbiAxOTcwLCBpbmNvbWUgZGlzdHJpYnV0aW9uIGlzIGJpbW9kYWwsIGNvbnNpc3RlbnQgd2l0aCB0aGUgZGljaG90b21vdXMgV2VzdGVybiB2ZXJzdXMgZGV2ZWxvcGluZyB3b3JsZHZpZXcuCmBgYHtyfQojIEFkZCBkb2xsYXJzIHBlciBkYXkgdmFyaWFibGUKZ2FwbWluZGVyIDwtIGdhcG1pbmRlciAlPiUKICAgIG11dGF0ZShkb2xsYXJzX3Blcl9kYXk9Z2RwL3BvcHVsYXRpb24vMzY1KQoKIyBIaXN0b2dyYW0gb2YgZG9sbGFycyBwZXIgZGF5CnBhc3RfeWVhciA8LSAxOTcwCmdhcG1pbmRlciAlPiUKICAgIGZpbHRlcih5ZWFyPT1wYXN0X3llYXIgJiAhaXMubmEoZ2RwKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKGRvbGxhcnNfcGVyX2RheSkpICsKICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTEsIGNvbG9yPSJibGFjayIpCiMgUmVwZWF0IGhpc3RvZ3JhbSB3aXRoIGxvZzIgc2NhbGVkIGRhdGEKZ2FwbWluZGVyICU+JQogICAgZmlsdGVyKHllYXI9PXBhc3RfeWVhciAmICFpcy5uYShnZHApKSAlPiUKICAgIGdncGxvdChhZXMobG9nMihkb2xsYXJzX3Blcl9kYXkpKSkgKwogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MSwgY29sb3I9ImJsYWNrIikKIyBSZXBlYXQgaGlzdG9ncmFtIHdpdGggbG9nMiBzY2FsZWQgeC1heGlzCmdhcG1pbmRlciAlPiUKICAgIGZpbHRlcih5ZWFyPT1wYXN0X3llYXIgJiAhaXMubmEoZ2RwKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKGRvbGxhcnNfcGVyX2RheSkpICsKICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTEsIGNvbG9yPSJibGFjayIpICsKICAgIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nMiIpCmBgYApfX18gCiMjIyMgKipUcmFuc2Zvcm1hdGlvbnMqKgoKPiDwn46eIFtTdHJhdGlmeSBhbmQgQm94cGxvdF0oaHR0cHM6Ly9lZHgtdmlkZW8ubmV0L0hBUkIwMjBEMjAxNy1WMDAyNjAwX0RUSC5tcDQpCj4gCj4g8J+TliBbQ29tcGFyaW5nIG11bHRpcGxlIGRpc3RyaWJ1dGlvbnMgd2l0aCBib3hwbG90cyBhbmQgcmlkZ2UgcGxvdHNdKGh0dHBzOi8vcmFmYWxhYi5naXRodWIuaW8vZHNib29rL2dhcG1pbmRlci5odG1sI2NvbXBhcmluZy1tdWx0aXBsZS1kaXN0cmlidXRpb25zLXdpdGgtYm94cGxvdHMtYW5kLXJpZGdlLXBsb3RzKQoKPiBOb3RlIHRoYXQgbWFueSBib3hwbG90cyBmcm9tIHRoZSB2aWRlbyBhcmUgaW5zdGVhZCBkb3QgcGxvdHMgaW4gdGhlIHRleHRib29rIGFuZCB0aGF0IGEgZGlmZmVyZW50IGJveHBsb3QgaXMgY29uc3RydWN0ZWQgaW4gdGhlIHRleHRib29rLiBBbHNvIHJlYWQgdGhhdCBzZWN0aW9uIHRvIHNlZSBhbiBleGFtcGxlIG9mIGdyb3VwaW5nIGZhY3RvcnMgd2l0aCB0aGUgY2FzZV93aGVuIGZ1bmN0aW9uLgoKLSBNYWtlIGJveHBsb3RzIHN0cmF0aWZpZWQgYnkgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB1c2luZyB0aGUgYGdlb21fYm94cGxvdCgpYCBnZW9tZXRyeS4KLSBSb3RhdGUgYXhpcyBsYWJlbHMgYnkgY2hhbmdpbmcgdGhlIHRoZW1lIHRocm91Z2ggYGVsZW1lbnRfdGV4dCgpYC4gWW91IGNhbiBjaGFuZ2UgdGhlIGFuZ2xlIGFuZCBqdXN0aWZpY2F0aW9uIG9mIHRoZSB0ZXh0IGxhYmVscy4KLSBDb25zaWRlciBvcmRlcmluZyB5b3VyIGZhY3RvcnMgYnkgYSBtZWFuaW5nZnVsIHZhbHVlIHdpdGggdGhlIGByZW9yZGVyKClgIGZ1bmN0aW9uLCB3aGljaCBjaGFuZ2VzIHRoZSBvcmRlciBvZiBmYWN0b3IgbGV2ZWxzIGJhc2VkIG9uIGEgcmVsYXRlZCBudW1lcmljIHZlY3Rvci4gVGhpcyBpcyBhIHdheSB0byBlYXNlIGNvbXBhcmlzb25zLgotIFNob3cgdGhlIGRhdGEgYnkgYWRkaW5nIGRhdGEgcG9pbnRzIHRvIHRoZSBib3hwbG90IHdpdGggYSBgZ2VvbV9wb2ludCgpYCBsYXllci4gVGhpcyBhZGRzIGluZm9ybWF0aW9uIGJleW9uZCB0aGUgZml2ZS1udW1iZXIgc3VtbWFyeSB0byB5b3VyIHBsb3QsIGJ1dCB0b28gbWFueSBkYXRhIHBvaW50cyBjYW4gb2JmdXNjYXRlIHlvdXIgbWVzc2FnZS4KCkNvZGU6IEJveHBsb3Qgb2YgR0RQIGJ5IHJlZ2lvbgpgYGB7cn0KIyBBZGQgZG9sbGFycyBwZXIgZGF5IHZhcmlhYmxlCmdhcG1pbmRlciA8LSBnYXBtaW5kZXIgJT4lCiAgICBtdXRhdGUoZG9sbGFyc19wZXJfZGF5PWdkcC9wb3B1bGF0aW9uLzM2NSkKIyBOdW1iZXIgb2YgcmVnaW9ucwpsZW5ndGgobGV2ZWxzKGdhcG1pbmRlciRyZWdpb24pKQojIEJveHBsb3Qgb2YgR0RQIGJ5IHJlZ2lvbiBpbiAxOTcwCnBhc3RfeWVhciA8LSAxOTcwCnAgPC0gZ2FwbWluZGVyICU+JQogICAgZmlsdGVyKHllYXIgPT0gcGFzdF95ZWFyICYgIWlzLm5hKGdkcCkpICU+JQogICAgZ2dwbG90KGFlcyhyZWdpb24sIGRvbGxhcnNfcGVyX2RheSkpCnAgKyBnZW9tX2JveHBsb3QoKQojIFJvdGF0ZSBuYW1lcyBvbiB4LWF4aXMKcCArIGdlb21fYm94cGxvdCgpICsKICAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSkpCmBgYApDb2RlOiBUaGUgcmVvcmRlciBmdW5jdGlvbgpgYGB7cn0KIyBCeSBkZWZhdWx0LCBmYWN0b3Igb3JkZXIgaXMgYWxwaGFiZXRpY2FsCmZhYyA8LSBmYWN0b3IoYygiQXNpYSIsICJBc2lhIiwgIldlc3QiLCAiV2VzdCIsICJXZXN0IikpCmxldmVscyhmYWMpCiMgUmVvcmRlciBmYWN0b3IgYnkgdGhlIGNhdGVnb3J5IG1lYW5zCnZhbHVlIDwtIGMoMTAsIDExLCAxMiwgNiwgNCkKZmFjIDwtIHJlb3JkZXIoZmFjLCB2YWx1ZSwgRlVOPW1lYW4pCmxldmVscyhmYWMpCmBgYApDb2RlOiBFbmhhbmNlZCBib3hwbG90IG9yZGVyZWQgYnkgbWVkaWFuIGluY29tZSwgc2NhbGVkLCBhbmQgc2hvd2luZyBkYXRhCmBgYHtyfQojIFJlb3JkZXIgYnkgbWVkaWFuIGluY29tZSBhbmQgY29sb3IgYnkgY29udGluZW50CnAgPC0gZ2FwbWluZGVyICU+JQogICAgZmlsdGVyKHllYXIgPT0gcGFzdF95ZWFyICYgIWlzLm5hKGdkcCkpICU+JQogICAgbXV0YXRlKHJlZ2lvbj1yZW9yZGVyKHJlZ2lvbiwgZG9sbGFyc19wZXJfZGF5LCBGVU49bWVkaWFuKSkgJT4lICAgICMgUmVvcmRlcgogICAgZ2dwbG90KGFlcyhyZWdpb24sIGRvbGxhcnNfcGVyX2RheSwgZmlsbD1jb250aW5lbnQpKSArICAgICMgQ29sb3IgYnkgY29udGluZW50CiAgICBnZW9tX2JveHBsb3QoKSArCiAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpKSArCiAgICB4bGFiKCIiKQpwCiMgbG9nMiBzY2FsZSB5LWF4aXMKcCArIHNjYWxlX3lfY29udGludW91cyh0cmFucz0ibG9nMiIpCiMgQWRkIGRhdGEgcG9pbnRzCnAgKyBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9ImxvZzIiKSArIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQ9RkFMU0UpCmBgYAoK