Correlations in R

1 Introduction

We will create Tables for Correlations, and graphs for Correlations in R. As always, we will consistently use the Project Mosaic ecosystem of packages in R (mosaic, mosaicData and ggformula).

Note the standard method for all commands from the mosaic package:

goal( y ~ x | z, data = mydata, …)

1.1 Case Study -1: Dataset from mosaicData

Let us inspect what datasets are available in the package mosaicData. Run this command in your Console:

# Run in Console
data(package = "mosaicData")

The popup tab shows a lot of datasets we could use. Let us continue to use the famous Galton dataset and inspect it:

data("Galton")
inspect(Galton)
#> 
#> categorical variables:  
#>     name  class levels   n missing
#> 1 family factor    197 898       0
#> 2    sex factor      2 898       0
#>                                    distribution
#> 1 185 (1.7%), 166 (1.2%), 66 (1.2%) ...        
#> 2 M (51.8%), F (48.2%)                         
#> 
#> quantitative variables:  
#>     name   class min Q1 median   Q3  max      mean       sd   n missing
#> 1 father numeric  62 68   69.0 71.0 78.5 69.232851 2.470256 898       0
#> 2 mother numeric  58 63   64.0 65.5 70.5 64.084410 2.307025 898       0
#> 3 height numeric  56 64   66.5 69.7 79.0 66.760690 3.582918 898       0
#> 4  nkids integer   1  4    6.0  8.0 15.0  6.135857 2.685156 898       0

The inspect command already gives us a series of statistical measures of different variables of interest. As discussed previously, we can retain the output of inspect and use it in our reports: (there are ways of dressing up these tables too)


galton_describe <- inspect(Galton)

galton_describe$categorical
galton_describe$quantitative

Try help("Galton") in your Console. The dataset is described as:

A data frame with 898 observations on the following variables.
- family a factor with levels for each family
- father the father’s height (in inches)
- mother the mother’s height (in inches)
- sex the child’s sex: F or M
- height the child’s height as an adult (in inches)
- nkids the number of adult children in the family, or, at least, the number whose heights Galton recorded.

There is a lot of Description generated by the mosaic::inspect() command ! What can we say about the dataset and its variables? How big is the dataset? How many variables? What types are they, Quant or Qual? If they are Qual, what are the levels? Are they ordered levels? Discuss!

1.2 Correlations and Plots

What Questions might we have, that we could answer with a Statistical Measure, or Correlation chart?

Q.1 Which are the variables that have significant pair-wise correlations? What polarity are these correlations?



# Pulling out the list of Quant variables from NHANES
galton_quant <- galton_describe$quantitative
galton_quant$name
#> [1] "father" "mother" "height" "nkids"

GGally::ggpairs(
  Galton,
  columns = c("father", "mother", "height", "nkids"),
  diag = list("densityDiag"),
  title = "Galton Data Correlations Plot"
)

Can we plot a Correlogram for this dataset?

#library(corrplot)

galton_num_var <- Galton %>% select(father, mother, height, nkids)
galton_cor <- cor(galton_num_var)
galton_correlogram <- galton_cor %>%
  corrplot(method = "ellipse",
           type = "lower",
           main = "Correlogram for Galton dataset")

galton_correlogram
#> $corr
#>             father      mother     height       nkids
#> father  1.00000000  0.07366461  0.2753548 -0.16002294
#> mother  0.07366461  1.00000000  0.2016549 -0.02002964
#> height  0.27535483  0.20165489  1.0000000 -0.12691012
#> nkids  -0.16002294 -0.02002964 -0.1269101  1.00000000
#> 
#> $corrPos
#>     xName  yName x y        corr
#> 1  father father 1 4  1.00000000
#> 2  father mother 1 3  0.07366461
#> 3  father height 1 2  0.27535483
#> 4  father  nkids 1 1 -0.16002294
#> 5  mother mother 2 3  1.00000000
#> 6  mother height 2 2  0.20165489
#> 7  mother  nkids 2 1 -0.02002964
#> 8  height height 3 2  1.00000000
#> 9  height  nkids 3 1 -0.12691012
#> 10  nkids  nkids 4 1  1.00000000
#> 
#> $arg
#> $arg$type
#> [1] "lower"

Clearly height is positively correlated to father and mother; interestingly, height is negatively correlated ( slightly) with nkids.

Q.2: Let us confirm with a test:

height ~ father:

mosaic::cor_test(height ~ father, data = Galton)
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and father
#> t = 8.5737, df = 896, p-value < 2.2e-16
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.2137851 0.3347455
#> sample estimates:
#>       cor 
#> 0.2753548

height ~ mother:

mosaic::cor_test(height ~ mother, data = Galton)
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and mother
#> t = 6.1628, df = 896, p-value = 1.079e-09
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.1380554 0.2635982
#> sample estimates:
#>       cor 
#> 0.2016549

Q.3 What does this correlation look when split by sex of Child?

Sons ~ Parents


# For the sons
cor_test(height ~ father, data = Galton %>% filter(sex == "M"))
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and father
#> t = 9.1498, df = 463, p-value < 2.2e-16
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.3114667 0.4656805
#> sample estimates:
#>       cor 
#> 0.3913174
cor_test(height ~ mother, data = Galton %>% filter(sex == "M"))
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and mother
#> t = 7.628, df = 463, p-value = 1.367e-13
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.2508178 0.4125305
#> sample estimates:
#>       cor 
#> 0.3341309

Daughters ~ Parents

# For the daughters
cor_test(height ~ father, data = Galton %>% filter(sex == "F"))
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and father
#> t = 10.719, df = 431, p-value < 2.2e-16
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.3809944 0.5300812
#> sample estimates:
#>       cor 
#> 0.4587605
cor_test(height ~ mother, data = Galton %>% filter(sex == "F"))
#> 
#>  Pearson's product-moment correlation
#> 
#> data:  height and mother
#> t = 6.8588, df = 431, p-value = 2.421e-11
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#>  0.2261463 0.3962226
#> sample estimates:
#>       cor 
#> 0.3136984

Q.4. How can we show this correlation in a set of Scatter Plots + Regression Lines? Can we recreate Galton’s famous diagram?

# For the sons
gf_point(height ~ father, 
         data = Galton %>% filter(sex == "M")) %>% 
  gf_smooth(method = "lm")


gf_point(height ~ mother, 
         data = Galton %>% filter(sex == "M")) %>% 
  gf_smooth(method = "lm")


# For the daughters
gf_point(height ~ father, 
         data = Galton %>% filter(sex == "F")) %>% 
  gf_smooth(method = "lm")


gf_point(height ~ mother, 
         data = Galton %>% filter(sex == "F")) %>% 
  gf_smooth(method = "lm")

An approximation to Galton’s famous plot:

gf_point(height ~ (father + mother)/2, data = Galton) %>% 
  gf_smooth(method = "lm") %>% 
  gf_density_2d(n = 8) %>% 
  gf_abline(slope = 1)

How would you interpret this plot?

1.3 Case Study -2: Dataset from NHANES

We will “live code” this in class!

2 Conclusion

We have a decent Correlations related workflow in R:

  • Load the dataset
  • inspect the dataset, identify Quant and Qual variables
  • Develop Pair-Wise plots + Correlations using GGally::ggpairs()
  • Develop Correlogram corrplot::corrplot
  • Check everything with a cor_test
  • Plot scatter plots using gf_point if needed.
  • Add extra lines using gf_abline() to compare hypotheses that you may have.

2.1 Reference

  1. https://en.wikipedia.org/wiki/Regression_toward_the_mean

  2. The Farnam Street Blog. Regression Toward the Mean: An Introduction with Examples. https://fs.blog/regression-to-the-mean/

LS0tDQp0aXRsZTogIkNvcnJlbGF0aW9ucyBpbiBSIg0KYXV0aG9yOiAiQXJ2aW5kIFZlbmthdGFkcmkiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOg0KICAgIGhpZ2hsaWdodDoga2F0ZQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIHRvY19kZXB0aDogMg0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCg0KIyBJbnRyb2R1Y3Rpb24NCg0KV2Ugd2lsbCBjcmVhdGUgVGFibGVzIGZvciBDb3JyZWxhdGlvbnMsIGFuZCBncmFwaHMgZm9yIENvcnJlbGF0aW9ucyBpbg0KUi4gQXMgYWx3YXlzLCB3ZSB3aWxsIGNvbnNpc3RlbnRseSB1c2UgdGhlIFsqKlByb2plY3QNCk1vc2FpYyoqXShodHRwczovL21vc2FpYy13ZWIub3JnKSBlY29zeXN0ZW0gb2YgcGFja2FnZXMgaW4gUiAoYG1vc2FpY2AsDQpgbW9zYWljRGF0YWAgYW5kIGBnZ2Zvcm11bGFgKS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBpbmNsdWRlPVRSVUV9DQprbml0cjo6b3B0c19jaHVuayRzZXQoY29sbGFwc2UgPSBULCBjb21tZW50ID0gIiM+IiwgZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICJjZW50ZXIiLGZpZy5oZWlnaHQgPSA0LCBmaWcud2lkdGggPSA2KQ0Kb3B0aW9ucyh0aWJibGUucHJpbnRfbWluID0gNEwsIHRpYmJsZS5wcmludF9tYXggPSA0TCkNCmxpYnJhcnkobW9zYWljKSAjIHBhY2thZ2UgZm9yIHN0YXRzLCBzaW11bGF0aW9ucywgYW5kIGJhc2ljIHBsb3RzDQpsaWJyYXJ5KG1vc2FpY0RhdGEpICMgcGFja2FnZSBjb250YWluaW5nIGRhdGFzZXRzDQpsaWJyYXJ5KGdnZm9ybXVsYSkgIyBwYWNrYWdlIGZvciBwcm9mZXNzaW9uYWwgbG9va2luZyBwbG90cywgdGhhdCB1c2UgdGhlIGZvcm11bGEgaW50ZXJmYWNlIGZyb20gbW9zYWljDQpsaWJyYXJ5KE5IQU5FUykgIyBzdXJ2ZXkgZGF0YSBjb2xsZWN0ZWQgYnkgdGhlIFVTIE5hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3MgKE5DSFMpDQpsaWJyYXJ5KGNvcnJwbG90KSAjIEZvciBDb3JyZWxvZ3JhbSBwbG90cw0KDQpgYGANCg0KOjo6IHsjbm90ZSAuaWxsdXN0cmF0aW9uIHN0eWxlPSJiYWNrZ3JvdW5kOiBiZWlnZSJ9DQpOb3RlIHRoZSBzdGFuZGFyZCBtZXRob2QgZm9yIGFsbCBjb21tYW5kcyBmcm9tIHRoZSBgbW9zYWljYCBwYWNrYWdlOg0KDQpgZ29hbCggeSB+IHggfCB6LCBkYXRhID0gbXlkYXRhLCDigKYpYA0KOjo6DQoNCiMjIENhc2UgU3R1ZHkgLTE6IERhdGFzZXQgZnJvbSBgbW9zYWljRGF0YWANCg0KTGV0IHVzIGluc3BlY3Qgd2hhdCBkYXRhc2V0cyBhcmUgYXZhaWxhYmxlIGluIHRoZSBwYWNrYWdlIGBtb3NhaWNEYXRhYC4NClJ1biB0aGlzIGNvbW1hbmQgaW4geW91ciBDb25zb2xlOg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMgUnVuIGluIENvbnNvbGUNCmRhdGEocGFja2FnZSA9ICJtb3NhaWNEYXRhIikNCg0KYGBgDQoNClRoZSBwb3B1cCB0YWIgc2hvd3MgYSBsb3Qgb2YgZGF0YXNldHMgd2UgY291bGQgdXNlLiBMZXQgdXMgY29udGludWUgdG8NCnVzZSB0aGUgZmFtb3VzIGBHYWx0b25gIGRhdGFzZXQgYW5kIGBpbnNwZWN0YCBpdDoNCg0KYGBge3J9DQpkYXRhKCJHYWx0b24iKQ0KaW5zcGVjdChHYWx0b24pDQoNCmBgYA0KDQpUaGUgYGluc3BlY3RgIGNvbW1hbmQgYWxyZWFkeSBnaXZlcyB1cyBhIHNlcmllcyBvZiBzdGF0aXN0aWNhbCBtZWFzdXJlcw0Kb2YgZGlmZmVyZW50IHZhcmlhYmxlcyBvZiBpbnRlcmVzdC4gQXMgZGlzY3Vzc2VkIHByZXZpb3VzbHksIHdlIGNhbg0KcmV0YWluIHRoZSBvdXRwdXQgb2YgYGluc3BlY3RgIGFuZCB1c2UgaXQgaW4gb3VyIHJlcG9ydHM6ICh0aGVyZSBhcmUNCndheXMgb2YgZHJlc3NpbmcgdXAgdGhlc2UgdGFibGVzIHRvbykNCg0KYGBge3IgR2FsdG9uLWluc3BlY3R9DQoNCmdhbHRvbl9kZXNjcmliZSA8LSBpbnNwZWN0KEdhbHRvbikNCg0KZ2FsdG9uX2Rlc2NyaWJlJGNhdGVnb3JpY2FsDQpnYWx0b25fZGVzY3JpYmUkcXVhbnRpdGF0aXZlDQoNCmBgYA0KDQpUcnkgYGhlbHAoIkdhbHRvbiIpYCBpbiB5b3VyIENvbnNvbGUuIFRoZSBkYXRhc2V0IGlzIGRlc2NyaWJlZCBhczoNCg0KPiBBIGRhdGEgZnJhbWUgd2l0aCA4OTggb2JzZXJ2YXRpb25zIG9uIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzLlwNCj4gLSBgZmFtaWx5YCBhIGZhY3RvciB3aXRoIGxldmVscyBmb3IgZWFjaCBmYW1pbHlcDQo+IC0gYGZhdGhlcmAgdGhlIGZhdGhlcidzIGhlaWdodCAoaW4gaW5jaGVzKVwNCj4gLSBgbW90aGVyYCB0aGUgbW90aGVyJ3MgaGVpZ2h0IChpbiBpbmNoZXMpXA0KPiAtIGBzZXhgIHRoZSBjaGlsZCdzIHNleDogRiBvciBNXA0KPiAtIGBoZWlnaHRgIHRoZSBjaGlsZCdzIGhlaWdodCBhcyBhbiBhZHVsdCAoaW4gaW5jaGVzKVwNCj4gLSBgbmtpZHNgIHRoZSBudW1iZXIgb2YgYWR1bHQgY2hpbGRyZW4gaW4gdGhlIGZhbWlseSwgb3IsIGF0IGxlYXN0LA0KPiB0aGUgbnVtYmVyIHdob3NlIGhlaWdodHMgR2FsdG9uIHJlY29yZGVkLg0KDQpUaGVyZSBpcyBhIGxvdCBvZiBEZXNjcmlwdGlvbiBnZW5lcmF0ZWQgYnkgdGhlIGBtb3NhaWM6Omluc3BlY3QoKWANCmNvbW1hbmQgISBXaGF0IGNhbiB3ZSBzYXkgYWJvdXQgdGhlIGRhdGFzZXQgYW5kIGl0cyB2YXJpYWJsZXM/IEhvdyBiaWcNCmlzIHRoZSBkYXRhc2V0PyBIb3cgbWFueSB2YXJpYWJsZXM/IFdoYXQgdHlwZXMgYXJlIHRoZXksIFF1YW50IG9yIFF1YWw/DQpJZiB0aGV5IGFyZSBRdWFsLCB3aGF0IGFyZSB0aGUgKmxldmVscyo/IEFyZSB0aGV5ICpvcmRlcmVkKiBsZXZlbHM/DQpEaXNjdXNzIQ0KDQojIyBDb3JyZWxhdGlvbnMgYW5kIFBsb3RzDQoNCldoYXQgUXVlc3Rpb25zIG1pZ2h0IHdlIGhhdmUsIHRoYXQgd2UgY291bGQgYW5zd2VyIHdpdGggYSBTdGF0aXN0aWNhbA0KTWVhc3VyZSwgb3IgQ29ycmVsYXRpb24gY2hhcnQ/DQoNClEuMSBXaGljaCBhcmUgdGhlIHZhcmlhYmxlcyB0aGF0IGhhdmUgc2lnbmlmaWNhbnQgcGFpci13aXNlDQpjb3JyZWxhdGlvbnM/IFdoYXQgcG9sYXJpdHkgYXJlIHRoZXNlIGNvcnJlbGF0aW9ucz8NCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCg0KDQojIFB1bGxpbmcgb3V0IHRoZSBsaXN0IG9mIFF1YW50IHZhcmlhYmxlcyBmcm9tIE5IQU5FUw0KZ2FsdG9uX3F1YW50IDwtIGdhbHRvbl9kZXNjcmliZSRxdWFudGl0YXRpdmUNCmdhbHRvbl9xdWFudCRuYW1lDQoNCkdHYWxseTo6Z2dwYWlycygNCiAgR2FsdG9uLA0KICBjb2x1bW5zID0gYygiZmF0aGVyIiwgIm1vdGhlciIsICJoZWlnaHQiLCAibmtpZHMiKSwNCiAgZGlhZyA9IGxpc3QoImRlbnNpdHlEaWFnIiksDQogIHRpdGxlID0gIkdhbHRvbiBEYXRhIENvcnJlbGF0aW9ucyBQbG90Ig0KKQ0KDQpgYGANCg0KQ2FuIHdlIHBsb3QgYSBDb3JyZWxvZ3JhbSBmb3IgdGhpcyBkYXRhc2V0Pw0KDQpgYGB7cn0NCiNsaWJyYXJ5KGNvcnJwbG90KQ0KDQpnYWx0b25fbnVtX3ZhciA8LSBHYWx0b24gJT4lIHNlbGVjdChmYXRoZXIsIG1vdGhlciwgaGVpZ2h0LCBua2lkcykNCmdhbHRvbl9jb3IgPC0gY29yKGdhbHRvbl9udW1fdmFyKQ0KZ2FsdG9uX2NvcnJlbG9ncmFtIDwtIGdhbHRvbl9jb3IgJT4lDQogIGNvcnJwbG90KG1ldGhvZCA9ICJlbGxpcHNlIiwNCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsDQogICAgICAgICAgIG1haW4gPSAiQ29ycmVsb2dyYW0gZm9yIEdhbHRvbiBkYXRhc2V0IikNCmdhbHRvbl9jb3JyZWxvZ3JhbQ0KDQpgYGANCg0KQ2xlYXJseSBgaGVpZ2h0YCBpcyBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgdG8gYGZhdGhlcmAgYW5kIGBtb3RoZXJgOw0KaW50ZXJlc3RpbmdseSwgYGhlaWdodGAgaXMgbmVnYXRpdmVseSBjb3JyZWxhdGVkICggc2xpZ2h0bHkpIHdpdGgNCmBua2lkc2AuDQoNClEuMjogTGV0IHVzIGNvbmZpcm0gd2l0aCBhIHRlc3Q6DQoNCmBoZWlnaHQgfiBmYXRoZXJgOg0KDQpgYGB7cn0NCm1vc2FpYzo6Y29yX3Rlc3QoaGVpZ2h0IH4gZmF0aGVyLCBkYXRhID0gR2FsdG9uKQ0KYGBgDQoNCmBoZWlnaHQgfiBtb3RoZXJgOg0KDQpgYGB7cn0NCm1vc2FpYzo6Y29yX3Rlc3QoaGVpZ2h0IH4gbW90aGVyLCBkYXRhID0gR2FsdG9uKQ0KYGBgDQoNClEuMyBXaGF0IGRvZXMgdGhpcyBjb3JyZWxhdGlvbiBsb29rIHdoZW4gc3BsaXQgYnkgYHNleGAgb2YgQ2hpbGQ/DQoNCmBTb25zIH4gUGFyZW50c2ANCg0KYGBge3J9DQoNCiMgRm9yIHRoZSBzb25zDQpjb3JfdGVzdChoZWlnaHQgfiBmYXRoZXIsIGRhdGEgPSBHYWx0b24gJT4lIGZpbHRlcihzZXggPT0gIk0iKSkNCmNvcl90ZXN0KGhlaWdodCB+IG1vdGhlciwgZGF0YSA9IEdhbHRvbiAlPiUgZmlsdGVyKHNleCA9PSAiTSIpKQ0KDQpgYGANCg0KYERhdWdodGVycyB+IFBhcmVudHNgDQoNCmBgYHtyfQ0KIyBGb3IgdGhlIGRhdWdodGVycw0KY29yX3Rlc3QoaGVpZ2h0IH4gZmF0aGVyLCBkYXRhID0gR2FsdG9uICU+JSBmaWx0ZXIoc2V4ID09ICJGIikpDQpjb3JfdGVzdChoZWlnaHQgfiBtb3RoZXIsIGRhdGEgPSBHYWx0b24gJT4lIGZpbHRlcihzZXggPT0gIkYiKSkNCiAgICAgICAgIA0KYGBgDQoNClEuNC4gSG93IGNhbiB3ZSBzaG93IHRoaXMgY29ycmVsYXRpb24gaW4gYSBzZXQgb2YgU2NhdHRlciBQbG90cyArDQpSZWdyZXNzaW9uIExpbmVzPyBDYW4gd2UgcmVjcmVhdGUgR2FsdG9uJ3MgZmFtb3VzIGRpYWdyYW0/DQoNCmBgYHtyfQ0KIyBGb3IgdGhlIHNvbnMNCmdmX3BvaW50KGhlaWdodCB+IGZhdGhlciwgDQogICAgICAgICBkYXRhID0gR2FsdG9uICU+JSBmaWx0ZXIoc2V4ID09ICJNIikpICU+JSANCiAgZ2Zfc21vb3RoKG1ldGhvZCA9ICJsbSIpDQoNCmdmX3BvaW50KGhlaWdodCB+IG1vdGhlciwgDQogICAgICAgICBkYXRhID0gR2FsdG9uICU+JSBmaWx0ZXIoc2V4ID09ICJNIikpICU+JSANCiAgZ2Zfc21vb3RoKG1ldGhvZCA9ICJsbSIpDQoNCiMgRm9yIHRoZSBkYXVnaHRlcnMNCmdmX3BvaW50KGhlaWdodCB+IGZhdGhlciwgDQogICAgICAgICBkYXRhID0gR2FsdG9uICU+JSBmaWx0ZXIoc2V4ID09ICJGIikpICU+JSANCiAgZ2Zfc21vb3RoKG1ldGhvZCA9ICJsbSIpDQoNCmdmX3BvaW50KGhlaWdodCB+IG1vdGhlciwgDQogICAgICAgICBkYXRhID0gR2FsdG9uICU+JSBmaWx0ZXIoc2V4ID09ICJGIikpICU+JSANCiAgZ2Zfc21vb3RoKG1ldGhvZCA9ICJsbSIpDQpgYGANCg0KQW4gYXBwcm94aW1hdGlvbiB0byBbR2FsdG9uJ3MgZmFtb3VzDQpwbG90XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SZWdyZXNzaW9uX3Rvd2FyZF90aGVfbWVhbik6DQoNCmBgYHtyfQ0KZ2ZfcG9pbnQoaGVpZ2h0IH4gKGZhdGhlciArIG1vdGhlcikvMiwgZGF0YSA9IEdhbHRvbikgJT4lIA0KICBnZl9zbW9vdGgobWV0aG9kID0gImxtIikgJT4lIA0KICBnZl9kZW5zaXR5XzJkKG4gPSA4KSAlPiUgDQogIGdmX2FibGluZShzbG9wZSA9IDEpDQpgYGANCg0KSG93IHdvdWxkIHlvdSBpbnRlcnByZXQgdGhpcyBwbG90Pw0KDQojIyBDYXNlIFN0dWR5IC0yOiBEYXRhc2V0IGZyb20gYE5IQU5FU2ANCg0KV2Ugd2lsbCAibGl2ZSBjb2RlIiB0aGlzIGluIGNsYXNzIQ0KDQojIENvbmNsdXNpb24NCg0KV2UgaGF2ZSBhIGRlY2VudCBDb3JyZWxhdGlvbnMgcmVsYXRlZCAqd29ya2Zsb3cqIGluIFI6XA0KDQotICAgTG9hZCB0aGUgZGF0YXNldA0KLSAgIGBpbnNwZWN0YCB0aGUgZGF0YXNldCwgaWRlbnRpZnkgUXVhbnQgYW5kIFF1YWwgdmFyaWFibGVzDQotICAgRGV2ZWxvcCBQYWlyLVdpc2UgcGxvdHMgKyBDb3JyZWxhdGlvbnMgdXNpbmcgYEdHYWxseTo6Z2dwYWlycygpYA0KLSAgIERldmVsb3AgQ29ycmVsb2dyYW0gYGNvcnJwbG90Ojpjb3JycGxvdGANCi0gICBDaGVjayBldmVyeXRoaW5nIHdpdGggYSBgY29yX3Rlc3RgDQotICAgUGxvdCBzY2F0dGVyIHBsb3RzIHVzaW5nIGBnZl9wb2ludGAgaWYgbmVlZGVkLg0KLSAgIEFkZCBleHRyYSBsaW5lcyB1c2luZyBgZ2ZfYWJsaW5lKClgIHRvIGNvbXBhcmUgaHlwb3RoZXNlcyB0aGF0IHlvdQ0KICAgIG1heSBoYXZlLg0KDQojIyBSZWZlcmVuY2UNCg0KMS4gIDxodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SZWdyZXNzaW9uX3Rvd2FyZF90aGVfbWVhbj4NCg0KMi4gIFRoZSBGYXJuYW0gU3RyZWV0IEJsb2cuICpSZWdyZXNzaW9uIFRvd2FyZCB0aGUgTWVhbjogQW4gSW50cm9kdWN0aW9uDQogICAgd2l0aCBFeGFtcGxlcy4qIDxodHRwczovL2ZzLmJsb2cvcmVncmVzc2lvbi10by10aGUtbWVhbi8+DQo=