ggplot2 examples

library(tidyverse)
library(mdsr)

CIACounties

Make the base plot g and then add different layers on to it.

head(CIACountries)
# base plot g
g <- CIACountries %>% ggplot(aes(y = gdp, x = educ)) 
g + geom_point()

g + geom_point(size = 3)

g + geom_point(aes(color = net_users), size = 3)

# no geom_point used for the next picture
g + geom_text( aes(label = country, color = net_users), size = 3 )

g + geom_point( aes(color = net_users, size = roadways) )

Change the scales

g + geom_point(aes(color = net_users, size = roadways)) +
  coord_trans( y = "log10")

g + geom_point(aes(color = net_users, size = roadways)) +
  scale_y_continuous(name = "Gross Domestic Product", trans = "log10")

Faceting

g + geom_point(alpha = 0.9, aes(size = roadways)) +
  coord_trans(y = "log10") +
  facet_wrap( ~ net_users, nrow = 1) +
  theme(legend.position = "top")

g + geom_point(alpha = 0.9, aes(size = roadways)) +
  coord_trans(y = "log10") +
  scale_y_continuous(name = "Gross Domestic Product", trans = "log10") +
  facet_wrap( ~ net_users, nrow = 1) +
  theme(legend.position = "top")

Export the data and try in Tableau

getwd()
[1] "/home/esuess/classes/2020-2021/01 - Fall 2020/Stat651/Presentations/02_ggplot2"
write_csv(CIACountries, "CIACountries.csv")

MedicareCharges

Check out the MEPS website for more real data.

# head(MedicareCharges) # This now causes an error, remove the grouping.
? MedicareCharges
MedicareCharges <- ungroup(MedicareCharges)
head(MedicareCharges)
NJCharges <- MedicareCharges %>% filter(stateProvider == "NJ")
NJCharges
p <- NJCharges %>% ggplot(aes(y = mean_charge, x = reorder(drg, mean_charge))) +
  geom_bar(fill = "grey", stat = "identity")
p

p <- p + ylab("Statewide Average Charges ($)") + 
         xlab("Medical Procedure (DRG)")
p

p <- p + theme(axis.text.x = element_text(angle = 90, hjust = 1))
p

Now add the overall data to the plot to compare with NJ.

p <- p + geom_point(data = MedicareCharges, size = 1, alpha = 0.3)
p

SAT

Here is the link to the College Board SAT website.

g <- SAT_2010 %>% ggplot(aes(x = math))
g + geom_histogram()

g + geom_histogram(binwidth = 10)

g + geom_density()

ggplot( data = head(SAT_2010, 10), aes( y = math, x = reorder(state, math) ) )  +
  geom_bar(stat = "identity")

Scatterplot with tend lines

g <- SAT_2010 %>% ggplot(aes(x = expenditure, y = math)) +
  geom_point()
g

g <- g + geom_smooth(method="lm", se = 0) +
  xlab("Average expenditure per student ($100)") +
  ylab("Average score on math SAT")
g

Add the trend line within groups representing rate of taking the test.

SAT_2010 <- SAT_2010 %>%
  mutate(SAT_rate = cut(sat_pct, breaks = c(0, 30, 60, 100), labels = c("low", "medium", "high") ))
g <- g %+% SAT_2010
g

g + aes(color = SAT_rate)

g +facet_wrap( ~ SAT_rate)

HELPPrct

Here is the link to the NSDUH website.

HELPrct %>% ggplot(aes(x = homeless)) +
  geom_bar(aes(fill = substance), position = "fill") +
  coord_flip()

NHANES

Here is the link to the NHANES website.

library(NHANES)
head(NHANES)

Take a sample first and then make the plot.

sample_n(NHANES, size = 1000) %>% ggplot(aes(x = Age, y = Height, color = Gender)) +
  geom_point() +
  geom_smooth() +
  xlab("Age (years)") +
  ylab("Height (cm)")

Here is an alternative plot using all the data. This is hexbin plot.

NHANES %>% ggplot(aes(x = Age, y = Height, color = Gender)) +
  geom_hex() +
  geom_smooth() +
  xlab("Age (years)") +
  ylab("Height (cm)")

library(mosaic)
head(NHANES)
NHANES2 <- NHANES %>% select(AgeDecade, BMI_WHO) 
head(NHANES2)
NHANES2_table <- table(NHANES2)
NHANES2_table
         BMI_WHO
AgeDecade 12.0_18.5 18.5_to_24.9 25.0_to_29.9 30.0_plus
    0-9         873          193           28         7
    10-19       280          664          244       172
    20-29        49          526          349       418
    30-39        10          394          433       495
    40-49        26          371          475       506
    50-59        15          314          487       477
    60-69         8          199          321       373
    70+           6          142          207       218
mosaicplot(NHANES2_table, color = TRUE)

Weather

library(macleish)
Loading required package: etl
head(whately_2015)
whately_2015 %>% ggplot(aes(x = when, y=temperature)) +
  geom_line(color = "darkgrey") +
  geom_smooth() +
  xlab(NULL) +
  ylab("Tempurature (degrees Fahrenheit)")

Here is the link to the choroplethr website.

library(choroplethr)
Loading required package: acs
Loading required package: XML

Attaching package: ‘acs’

The following object is masked from ‘package:dplyr’:

    combine

The following object is masked from ‘package:base’:

    apply

View the Choroplethr documentation at www.Choroplethr.com
library(choroplethrMaps)
library(rUnemploymentData)
animated_state_unemployment_choropleth()
[1] "All files will be written to the current working directory: /home/esuess/classes/2020-2021/01 - Fall 2020/Stat651/Presentations/02_ggplot2 . To change this use setwd()"
[1] "Now writing individual choropleth files there as 'choropleth_1.png', 'choropleth_2.png', etc."
Saving 7 x 7 in image
[1] "Now writing code to animate all images in 'animated_choropleth.html'.  Please open that file with a browser."
# animated_county_unemployment_choropleth()

Networks

Check out ggnet2 or the newer ggnetwork

Example 4.

library(GGally)
library(network)
network: Classes for Relational Data
Version 1.16.0 created on 2019-11-30.
copyright (c) 2005, Carter T. Butts, University of California-Irvine
                    Mark S. Handcock, University of California -- Los Angeles
                    David R. Hunter, Penn State University
                    Martina Morris, University of Washington
                    Skye Bender-deMoll, University of Washington
 For citation information, type citation("network").
 Type help("network-package") to get started.
library(sna)
Loading required package: statnet.common

Attaching package: ‘statnet.common’

The following object is masked from ‘package:base’:

    order

sna: Tools for Social Network Analysis
Version 2.5 created on 2019-12-09.
copyright (c) 2005, Carter T. Butts, University of California-Irvine
 For citation information, type citation("sna").
 Type help(package="sna") to get started.
library(ggplot2)
# root URL
r = "https://raw.githubusercontent.com/briatte/ggnet/master/"
# read nodes
v = read.csv(paste0(r, "inst/extdata/nodes.tsv"), sep = "\t")
names(v)
[1] "Sexe"                   "Prénom"                 "Nom"                    "Groupe"                
[5] "Département.d.élection" "Num.circonscription"    "Commission.permanente"  "Twitter"               
# read edges
e = read.csv(paste0(r, "inst/extdata/network.tsv"), sep = "\t")
names(e)
[1] "Source" "Target"
# network object
net = network(e, directed = TRUE)
# party affiliation
x = data.frame(Twitter = network.vertex.names(net))
x = merge(x, v, by = "Twitter", sort = FALSE)$Groupe
net %v% "party" = as.character(x)
# color palette
y = RColorBrewer::brewer.pal(9, "Set1")[ c(3, 1, 9, 6, 8, 5, 2) ]
names(y) = levels(x)
# network plot
ggnet2(net, color = "party", palette = y, alpha = 0.75, size = 4, edge.alpha = 0.5)

Review Table 3.3 on page 47 for the different kinds of plots that can be made for different kinds of x, y variables.

Continue with the Extended example: Historical baby names on page 48.

LS0tCnRpdGxlOiAiU3RhdC4gNjUxIGdncGxvdDIiCmF1dGhvcjogIlByb2YuIEVyaWMgQS4gU3Vlc3MiCm91dHB1dDoKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCmdncGxvdDIgZXhhbXBsZXMKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1kc3IpCmBgYAoKIyBDSUFDb3VudGllcwoKTWFrZSB0aGUgYmFzZSBwbG90ICoqZyoqIGFuZCB0aGVuIGFkZCBkaWZmZXJlbnQgbGF5ZXJzIG9uIHRvIGl0LgoKYGBge3J9CmhlYWQoQ0lBQ291bnRyaWVzKQoKIyBiYXNlIHBsb3QgZwoKZyA8LSBDSUFDb3VudHJpZXMgJT4lIGdncGxvdChhZXMoeSA9IGdkcCwgeCA9IGVkdWMpKSAKCmcgKyBnZW9tX3BvaW50KCkKCmcgKyBnZW9tX3BvaW50KHNpemUgPSAzKQoKZyArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gbmV0X3VzZXJzKSwgc2l6ZSA9IDMpCgojIG5vIGdlb21fcG9pbnQgdXNlZCBmb3IgdGhlIG5leHQgcGljdHVyZQoKZyArIGdlb21fdGV4dCggYWVzKGxhYmVsID0gY291bnRyeSwgY29sb3IgPSBuZXRfdXNlcnMpLCBzaXplID0gMyApCgpnICsgZ2VvbV9wb2ludCggYWVzKGNvbG9yID0gbmV0X3VzZXJzLCBzaXplID0gcm9hZHdheXMpICkKCmBgYAoKQ2hhbmdlIHRoZSBzY2FsZXMKCmBgYHtyfQpnICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBuZXRfdXNlcnMsIHNpemUgPSByb2Fkd2F5cykpICsKICBjb29yZF90cmFucyggeSA9ICJsb2cxMCIpCgpnICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBuZXRfdXNlcnMsIHNpemUgPSByb2Fkd2F5cykpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJHcm9zcyBEb21lc3RpYyBQcm9kdWN0IiwgdHJhbnMgPSAibG9nMTAiKQoKYGBgCgoKIyBGYWNldGluZwoKYGBge3J9CmcgKyBnZW9tX3BvaW50KGFscGhhID0gMC45LCBhZXMoc2l6ZSA9IHJvYWR3YXlzKSkgKwogIGNvb3JkX3RyYW5zKHkgPSAibG9nMTAiKSArCiAgZmFjZXRfd3JhcCggfiBuZXRfdXNlcnMsIG5yb3cgPSAxKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgpnICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuOSwgYWVzKHNpemUgPSByb2Fkd2F5cykpICsKICBjb29yZF90cmFucyh5ID0gImxvZzEwIikgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkdyb3NzIERvbWVzdGljIFByb2R1Y3QiLCB0cmFucyA9ICJsb2cxMCIpICsKICBmYWNldF93cmFwKCB+IG5ldF91c2VycywgbnJvdyA9IDEpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKYGBgCgoKIyBFeHBvcnQgdGhlIGRhdGEgYW5kIHRyeSBpbiBUYWJsZWF1CgpgYGB7cn0KZ2V0d2QoKQoKd3JpdGVfY3N2KENJQUNvdW50cmllcywgIkNJQUNvdW50cmllcy5jc3YiKQpgYGAKCgojIE1lZGljYXJlQ2hhcmdlcwoKQ2hlY2sgb3V0IHRoZSBbTUVQU10oaHR0cHM6Ly9tZXBzLmFocnEuZ292L21lcHN3ZWIvKSB3ZWJzaXRlIGZvciBtb3JlIHJlYWwgZGF0YS4KCmBgYHtyfQojIGhlYWQoTWVkaWNhcmVDaGFyZ2VzKSAjIFRoaXMgbm93IGNhdXNlcyBhbiBlcnJvciwgcmVtb3ZlIHRoZSBncm91cGluZy4KCj8gTWVkaWNhcmVDaGFyZ2VzCgpNZWRpY2FyZUNoYXJnZXMgPC0gdW5ncm91cChNZWRpY2FyZUNoYXJnZXMpCgpoZWFkKE1lZGljYXJlQ2hhcmdlcykKCk5KQ2hhcmdlcyA8LSBNZWRpY2FyZUNoYXJnZXMgJT4lIGZpbHRlcihzdGF0ZVByb3ZpZGVyID09ICJOSiIpCk5KQ2hhcmdlcwpgYGAKCmBgYHtyfQpwIDwtIE5KQ2hhcmdlcyAlPiUgZ2dwbG90KGFlcyh5ID0gbWVhbl9jaGFyZ2UsIHggPSByZW9yZGVyKGRyZywgbWVhbl9jaGFyZ2UpKSkgKwogIGdlb21fYmFyKGZpbGwgPSAiZ3JleSIsIHN0YXQgPSAiaWRlbnRpdHkiKQpwCgpwIDwtIHAgKyB5bGFiKCJTdGF0ZXdpZGUgQXZlcmFnZSBDaGFyZ2VzICgkKSIpICsgCiAgICAgICAgIHhsYWIoIk1lZGljYWwgUHJvY2VkdXJlIChEUkcpIikKcAoKcCA8LSBwICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKcApgYGAKCk5vdyBhZGQgdGhlIG92ZXJhbGwgZGF0YSB0byB0aGUgcGxvdCB0byBjb21wYXJlIHdpdGggTkouCgpgYGB7cn0KcCA8LSBwICsgZ2VvbV9wb2ludChkYXRhID0gTWVkaWNhcmVDaGFyZ2VzLCBzaXplID0gMSwgYWxwaGEgPSAwLjMpCnAKYGBgCgojIFNBVAoKSGVyZSBpcyB0aGUgbGluayB0byB0aGUgW0NvbGxlZ2UgQm9hcmQgU0FUXShodHRwczovL3Jlc2VhcmNoLmNvbGxlZ2Vib2FyZC5vcmcvcHJvZ3JhbXMvc2F0L2RhdGEpIHdlYnNpdGUuCgpgYGB7cn0KZyA8LSBTQVRfMjAxMCAlPiUgZ2dwbG90KGFlcyh4ID0gbWF0aCkpCgpnICsgZ2VvbV9oaXN0b2dyYW0oKQoKZyArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTApCgpnICsgZ2VvbV9kZW5zaXR5KCkKYGBgCgpgYGB7cn0KZ2dwbG90KCBkYXRhID0gaGVhZChTQVRfMjAxMCwgMTApLCBhZXMoIHkgPSBtYXRoLCB4ID0gcmVvcmRlcihzdGF0ZSwgbWF0aCkgKSApICArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpCmBgYAoKU2NhdHRlcnBsb3Qgd2l0aCB0ZW5kIGxpbmVzCgpgYGB7cn0KZyA8LSBTQVRfMjAxMCAlPiUgZ2dwbG90KGFlcyh4ID0gZXhwZW5kaXR1cmUsIHkgPSBtYXRoKSkgKwogIGdlb21fcG9pbnQoKQpnCgpnIDwtIGcgKyBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2UgPSAwKSArCiAgeGxhYigiQXZlcmFnZSBleHBlbmRpdHVyZSBwZXIgc3R1ZGVudCAoJDEwMCkiKSArCiAgeWxhYigiQXZlcmFnZSBzY29yZSBvbiBtYXRoIFNBVCIpCmcKYGBgCgpBZGQgdGhlIHRyZW5kIGxpbmUgd2l0aGluIGdyb3VwcyByZXByZXNlbnRpbmcgcmF0ZSBvZiB0YWtpbmcgdGhlIHRlc3QuCgpgYGB7cn0KU0FUXzIwMTAgPC0gU0FUXzIwMTAgJT4lCiAgbXV0YXRlKFNBVF9yYXRlID0gY3V0KHNhdF9wY3QsIGJyZWFrcyA9IGMoMCwgMzAsIDYwLCAxMDApLCBsYWJlbHMgPSBjKCJsb3ciLCAibWVkaXVtIiwgImhpZ2giKSApKQoKZyA8LSBnICUrJSBTQVRfMjAxMApnCgpnICsgYWVzKGNvbG9yID0gU0FUX3JhdGUpCgpnICtmYWNldF93cmFwKCB+IFNBVF9yYXRlKQpgYGAKCiMgSEVMUFByY3QKCkhlcmUgaXMgdGhlIGxpbmsgdG8gdGhlIFtOU0RVSF0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL2RhdGEtd2UtY29sbGVjdC9uc2R1aC1uYXRpb25hbC1zdXJ2ZXktZHJ1Zy11c2UtYW5kLWhlYWx0aCkgd2Vic2l0ZS4KCmBgYHtyfQpIRUxQcmN0ICU+JSBnZ3Bsb3QoYWVzKHggPSBob21lbGVzcykpICsKICBnZW9tX2JhcihhZXMoZmlsbCA9IHN1YnN0YW5jZSksIHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKIyBOSEFORVMKCkhlcmUgaXMgdGhlIGxpbmsgdG8gdGhlIFtOSEFORVNdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9uaGFuZXMvaW5kZXguaHRtKSB3ZWJzaXRlLgoKYGBge3J9CmxpYnJhcnkoTkhBTkVTKQoKaGVhZChOSEFORVMpCmBgYAoKVGFrZSBhIHNhbXBsZSBmaXJzdCBhbmQgdGhlbiBtYWtlIHRoZSBwbG90LiAgCgpgYGB7cn0Kc2FtcGxlX24oTkhBTkVTLCBzaXplID0gMTAwMCkgJT4lIGdncGxvdChhZXMoeCA9IEFnZSwgeSA9IEhlaWdodCwgY29sb3IgPSBHZW5kZXIpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aCgpICsKICB4bGFiKCJBZ2UgKHllYXJzKSIpICsKICB5bGFiKCJIZWlnaHQgKGNtKSIpCmBgYAoKSGVyZSBpcyBhbiBhbHRlcm5hdGl2ZSBwbG90IHVzaW5nIGFsbCB0aGUgZGF0YS4gIFRoaXMgaXMgaGV4YmluIHBsb3QuCgpgYGB7cn0KTkhBTkVTICU+JSBnZ3Bsb3QoYWVzKHggPSBBZ2UsIHkgPSBIZWlnaHQsIGNvbG9yID0gR2VuZGVyKSkgKwogIGdlb21faGV4KCkgKwogIGdlb21fc21vb3RoKCkgKwogIHhsYWIoIkFnZSAoeWVhcnMpIikgKwogIHlsYWIoIkhlaWdodCAoY20pIikKYGBgCgpgYGB7cn0KbGlicmFyeShtb3NhaWMpCgpoZWFkKE5IQU5FUykKCk5IQU5FUzIgPC0gTkhBTkVTICU+JSBzZWxlY3QoQWdlRGVjYWRlLCBCTUlfV0hPKSAKaGVhZChOSEFORVMyKQoKTkhBTkVTMl90YWJsZSA8LSB0YWJsZShOSEFORVMyKQpOSEFORVMyX3RhYmxlCgptb3NhaWNwbG90KE5IQU5FUzJfdGFibGUsIGNvbG9yID0gVFJVRSkKCmBgYAoKCiMgV2VhdGhlciAKCmBgYHtyfQpsaWJyYXJ5KG1hY2xlaXNoKQoKaGVhZCh3aGF0ZWx5XzIwMTUpCgp3aGF0ZWx5XzIwMTUgJT4lIGdncGxvdChhZXMoeCA9IHdoZW4sIHk9dGVtcGVyYXR1cmUpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImRhcmtncmV5IikgKwogIGdlb21fc21vb3RoKCkgKwogIHhsYWIoTlVMTCkgKwogIHlsYWIoIlRlbXB1cmF0dXJlIChkZWdyZWVzIEZhaHJlbmhlaXQpIikKYGBgCgpIZXJlIGlzIHRoZSBsaW5rIHRvIHRoZSBbY2hvcm9wbGV0aHJdKGh0dHBzOi8vYXJpbGFtc3RlaW4uY29tL29wZW4tc291cmNlLykgd2Vic2l0ZS4KCmBgYHtyfQpsaWJyYXJ5KGNob3JvcGxldGhyKQpsaWJyYXJ5KGNob3JvcGxldGhyTWFwcykKbGlicmFyeShyVW5lbXBsb3ltZW50RGF0YSkKCmFuaW1hdGVkX3N0YXRlX3VuZW1wbG95bWVudF9jaG9yb3BsZXRoKCkKCiMgYW5pbWF0ZWRfY291bnR5X3VuZW1wbG95bWVudF9jaG9yb3BsZXRoKCkKCmBgYAoKIyBOZXR3b3JrcwoKQ2hlY2sgb3V0IFtnZ25ldDJdKGh0dHBzOi8vYnJpYXR0ZS5naXRodWIuaW8vZ2duZXQvKSBvciB0aGUgbmV3ZXIgW2dnbmV0d29ya10oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ25ldHdvcmsvKQoKRXhhbXBsZSA0LgoKYGBge3J9CmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KG5ldHdvcmspCmxpYnJhcnkoc25hKQpsaWJyYXJ5KGdncGxvdDIpCgojIHJvb3QgVVJMCnIgPSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2JyaWF0dGUvZ2duZXQvbWFzdGVyLyIKCiMgcmVhZCBub2Rlcwp2ID0gcmVhZC5jc3YocGFzdGUwKHIsICJpbnN0L2V4dGRhdGEvbm9kZXMudHN2IiksIHNlcCA9ICJcdCIpCm5hbWVzKHYpCgojIHJlYWQgZWRnZXMKZSA9IHJlYWQuY3N2KHBhc3RlMChyLCAiaW5zdC9leHRkYXRhL25ldHdvcmsudHN2IiksIHNlcCA9ICJcdCIpCm5hbWVzKGUpCgojIG5ldHdvcmsgb2JqZWN0Cm5ldCA9IG5ldHdvcmsoZSwgZGlyZWN0ZWQgPSBUUlVFKQoKIyBwYXJ0eSBhZmZpbGlhdGlvbgp4ID0gZGF0YS5mcmFtZShUd2l0dGVyID0gbmV0d29yay52ZXJ0ZXgubmFtZXMobmV0KSkKeCA9IG1lcmdlKHgsIHYsIGJ5ID0gIlR3aXR0ZXIiLCBzb3J0ID0gRkFMU0UpJEdyb3VwZQpuZXQgJXYlICJwYXJ0eSIgPSBhcy5jaGFyYWN0ZXIoeCkKCiMgY29sb3IgcGFsZXR0ZQp5ID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDksICJTZXQxIilbIGMoMywgMSwgOSwgNiwgOCwgNSwgMikgXQpuYW1lcyh5KSA9IGxldmVscyh4KQoKIyBuZXR3b3JrIHBsb3QKZ2duZXQyKG5ldCwgY29sb3IgPSAicGFydHkiLCBwYWxldHRlID0geSwgYWxwaGEgPSAwLjc1LCBzaXplID0gNCwgZWRnZS5hbHBoYSA9IDAuNSkKCmBgYAoKUmV2aWV3IFRhYmxlIDMuMyBvbiBwYWdlIDQ3IGZvciB0aGUgZGlmZmVyZW50IGtpbmRzIG9mIHBsb3RzIHRoYXQgY2FuIGJlIG1hZGUgZm9yIGRpZmZlcmVudCBraW5kcyBvZiB4LCB5IHZhcmlhYmxlcy4KCgpDb250aW51ZSB3aXRoIHRoZSBFeHRlbmRlZCBleGFtcGxlOiBIaXN0b3JpY2FsIGJhYnkgbmFtZXMgb24gcGFnZSA0OC4KCgoKCgoK