Introduction
As a Social Psychologist first trained in SPSS, I am used to collecting and organizing my data in wide format. When data in is wide format, a subject’s responses will be in a single row, and each response is in separate columns. However R prefers long format. We could melt
and cast
with reshape2
to reshape from wide to long format, but is there a way to reshape using even less code? Luckily for us, Hadley Wickham has created the easy to use tidyr
!
tidyr
allow us to quickly and easily tidy and reorganize our data for all sorts of analyses. This is particularly helpful with a disorganized dataset. tidyr
is built for this function, and thus does less than reshape2. Specifically, tidyr
can only be used with exisiting dataframes, and cannot aggregate.
In this chapter, I will go over the hallmark functions of tidyr
: gather()
, separate()
, unite()
, and spread()
.
First let’s install and call up the tidyr
package. We will also need to use the dplyr
package.
#install.packages("tidyr") # I have used "#" to "comment out" this line for this tutorial. Just take away the first "#" and you are good to go!
#install.packages("dplyr")
library(tidyr)
library(dplyr)
%>%
Why do we need dplyr
? dplyr
is a grammar of data manipulation. We need dplyr
to use the pipe operator, %>%
, in our code. %>%
is not required to use tidyr, but it does make things easier!
%>%
allows you to pipe a value forward into an expression or to function call; such that x %>% f
, instead of f(x)
. This short hand was created by Stefan Milton Bache with the magrittr
package. To read more about this function, click here
The Dataframe
Here I have created a messy wide dataset. Feel free to use it to follow along!
In this example study, participants were asked to categorize three faces by clicking various buttons that represent three different categories. The time it took to click a button is in milliseconds.
n=10
wide <- data.frame(
ID = c(1:n),
Face.1 = c(411,723,325,456,579,612,709,513,527,379),
Face.2 = c(123,300,400,500,600,654,789,906,413,567),
Face.3 = c(1457,1000,569,896,956,2345,780,599,1023,678)
)
This dataset I created is messy; As you can see below, only ID is in a column, Response time split between three columns, such that responses are in both rows and columns (by ID and Face.1, Face.2, and Face.3).
What we want instead is one column for the condition (Face.1, Face.2, or Face.3) responses and a column for response time, with each row being a singualar observation for each participant. Participant IDs should repeat as this is a within subject design (each participant saw each face).
## ID Face.1 Face.2 Face.3
## 1 1 411 123 1457
## 2 2 723 300 1000
## 3 3 325 400 569
## 4 4 456 500 896
## 5 5 579 600 956
## 6 6 612 654 2345
## 7 7 709 789 780
## 8 8 513 906 599
## 9 9 527 413 1023
## 10 10 379 567 678
Gather()
By using the gather()
function, we can transform the data from wide to long Here is the generic code for gather()
:
#gather(data, key, value, ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
Gather() Arguments
Whoa! What does this all mean? Let’s find out more about the arguments of gather()
:
data
: Your data frame.
key, value
: The unquoted new names of key and value columns to create in the output. The key will become the name of the condition/IV column, and value will become the name of the response/DV column.
...
: The columns to gather. Use the exisiting variable names. Select a range of variables with :
(e.g. if you have variables a, b, c, and d, and want to select all of these varibeles you will indicate this with a:d). If you want to exclude a variable, use -
(e.g. exclude y with -y).
na.rm
: If you indicate that na.rm=TRUE, this will remove rows from the output where the value is missing.
convert
: If TRUE this will automatically convert the key column to a logical, integer, numeric, complex, or factor as appropriate. This is useful if the column names are actually numeric, integer, or logical.
factor_key
: If FALSE, the default, the key values will be stored as a character vector. If TRUE, will be stored as a factor, which preserves the original ordering of the columns.
Using Gather()
Now that we have a better understanding of the arguements, lets make our data set long using gather()
!
long <- wide %>% gather(Face, ResponseTime, Face.1:Face.3)
## ID Face ResponseTime
## 1 1 Face.1 411
## 2 2 Face.1 723
## 3 3 Face.1 325
## 4 4 Face.1 456
## 5 5 Face.1 579
## 6 6 Face.1 612
## 7 7 Face.1 709
## 8 8 Face.1 513
## 9 9 Face.1 527
## 10 10 Face.1 379
## 11 1 Face.2 123
## 12 2 Face.2 300
## 13 3 Face.2 400
## 14 4 Face.2 500
## 15 5 Face.2 600
## 16 6 Face.2 654
## 17 7 Face.2 789
## 18 8 Face.2 906
## 19 9 Face.2 413
## 20 10 Face.2 567
## 21 1 Face.3 1457
## 22 2 Face.3 1000
## 23 3 Face.3 569
## 24 4 Face.3 896
## 25 5 Face.3 956
## 26 6 Face.3 2345
## 27 7 Face.3 780
## 28 8 Face.3 599
## 29 9 Face.3 1023
## 30 10 Face.3 678
As you can see, now we have two columns: One for the the Faces, and one for response time. Each participant saw each face, so ID repeats three times.
Separate()
Although the long dataset we created using gather()
is acceptable for use, we can break down the face variable even further using separate()
.
Here is the generic code for separate()
:
#separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE, convert = FALSE, extra = "warn", fill = "warn")
Separate() Arguments
What are the arugments unique to separate()
?
col
: Unquoted name of the column to be separated.
into
: Names for the new variables that you are separating out from the column.
sep
: Separator between columns. If the seprator is a character, it is interpreted as a regular expression. The default value is a regular expression that matches any sequence of non-alphanumeric values. In the example, each face is indicated by a number that follows a period (.
). I do not need speifcy this because this exists in each level of Face. If numeric, it is interpreted as the position to split at. Positive values start at 1 at the far-left of the string; negative value start at -1 at the far-right of the string. The length of sep
should be one less than into
.
remove
: If this is TRUE, it removes the input column from output data frame.
extra
: If sep
is a character vector (like .
), this controls what happens when there are too many pieces (e.g. Face.1.A, rather than Face.1). There are three valid options: “warn” (the default): emit a warning and drop extra values. “drop”: drop any extra values without a warning. “merge”: only splits at most length(into) times
fill
: If sep
is a character vector (like .
), this controls what happens when there are not enough pieces (e.g. Face1, rather than Face.1). There are three valid options: “warn” (the default): emit a warning and fill from the right “right”: fill with missing values on the right “left”: fill with missing values on the left
Using Separate()
Each face is indicated by number after a period. This variable annotation allows us to separate the face variable into two. By using the separate
function of tidyr
we can tease apart single variables which sometimes capture multiple variables (or sometimes redundant information).
In this case, I want to split the Face from the number attached to it, which in this example represents the race of the face.
long_separate <- long %>% separate(Face, c("Target", "Number"))
## ID Target Number ResponseTime
## 1 1 Face 1 411
## 2 2 Face 1 723
## 3 3 Face 1 325
## 4 4 Face 1 456
## 5 5 Face 1 579
## 6 6 Face 1 612
## 7 7 Face 1 709
## 8 8 Face 1 513
## 9 9 Face 1 527
## 10 10 Face 1 379
## 11 1 Face 2 123
## 12 2 Face 2 300
## 13 3 Face 2 400
## 14 4 Face 2 500
## 15 5 Face 2 600
## 16 6 Face 2 654
## 17 7 Face 2 789
## 18 8 Face 2 906
## 19 9 Face 2 413
## 20 10 Face 2 567
## 21 1 Face 3 1457
## 22 2 Face 3 1000
## 23 3 Face 3 569
## 24 4 Face 3 896
## 25 5 Face 3 956
## 26 6 Face 3 2345
## 27 7 Face 3 780
## 28 8 Face 3 599
## 29 9 Face 3 1023
## 30 10 Face 3 678
Now, We have two columns, one for Target, the values of which are all “Face”, and one for Number, which indicates which of the three faces it is.
Unite
To undo separate()
, we can use unite()
, which merges two variables into one.
Here is the generic code for unite()
:
#unite(data, col, ..., sep = ".", remove = TRUE)
Unite() Arguments
Here are the arugments unique to unite()
:
sep
: In the code for unite()
the sep
indicated the separator we choose to to use to bind values. In this case, we are using .
Using Unite()
long_unite <- long_separate %>% unite(Face, Target, Number, sep = ".")
## ID Face ResponseTime
## 1 1 Face.1 411
## 2 2 Face.1 723
## 3 3 Face.1 325
## 4 4 Face.1 456
## 5 5 Face.1 579
## 6 6 Face.1 612
## 7 7 Face.1 709
## 8 8 Face.1 513
## 9 9 Face.1 527
## 10 10 Face.1 379
## 11 1 Face.2 123
## 12 2 Face.2 300
## 13 3 Face.2 400
## 14 4 Face.2 500
## 15 5 Face.2 600
## 16 6 Face.2 654
## 17 7 Face.2 789
## 18 8 Face.2 906
## 19 9 Face.2 413
## 20 10 Face.2 567
## 21 1 Face.3 1457
## 22 2 Face.3 1000
## 23 3 Face.3 569
## 24 4 Face.3 896
## 25 5 Face.3 956
## 26 6 Face.3 2345
## 27 7 Face.3 780
## 28 8 Face.3 599
## 29 9 Face.3 1023
## 30 10 Face.3 678
As you can see the data now looks like it did when we first transfromed from wide to long using gather()
!
Spread
Finally, we will transform the data from long back to wide with the spread()
function.
Here is the generic code for spread()
#spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)
Spread() Arguments
The arugments unique to spread()
:
key
: The unquoted name of the column whose values will be used as column headings.
value
: The unquoted name of the column whose values will populate the cells.
fill
: If used, missing values will be replaced with this value. There are two types of missing in the input: explicit missing values (i.e. NA
), and implicit missings, rows that simply aren’t present. Both types of missing value will be replaced by fill
.
convert
: If TRUE
, this will automatically convert the new columns to a logical, integer, numeric, complex, or factor as appropriate.
drop
: If FALSE
, will keep factor levels that don’t appear in the data, filling in missing combinations with fill
.
sep
: If NULL
, the column names will be taken from the values of key variable. If non-NULL
, the column names will be created by stringing together the name, separator, and value.
back_to_wide <- long_unite %>% spread(Face, ResponseTime)
## ID Face.1 Face.2 Face.3
## 1 1 411 123 1457
## 2 2 723 300 1000
## 3 3 325 400 569
## 4 4 456 500 896
## 5 5 579 600 956
## 6 6 612 654 2345
## 7 7 709 789 780
## 8 8 513 906 599
## 9 9 527 413 1023
## 10 10 379 567 678
And there we have it! We have come full circle back into wide.
LS0tDQp0aXRsZTogIkNoYXB0ZXIgOTogUmVzaGFwaW5nIERhdGEgVXNpbmcgVGlkeXIiDQphdXRob3I6ICJPbGl2aWEgTC4gSG9sbWVzIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICBmb250c2l6ZTogOHB0DQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KI0ludHJvZHVjdGlvbg0KDQpBcyBhIFNvY2lhbCBQc3ljaG9sb2dpc3QgZmlyc3QgdHJhaW5lZCBpbiBTUFNTLCBJIGFtIHVzZWQgdG8gY29sbGVjdGluZyBhbmQgb3JnYW5pemluZyBteSBkYXRhIGluIHdpZGUgZm9ybWF0LiBXaGVuIGRhdGEgaW4gaXMgd2lkZSBmb3JtYXQsIGEgc3ViamVjdOKAmXMgcmVzcG9uc2VzIHdpbGwgYmUgaW4gYSBzaW5nbGUgcm93LCBhbmQgZWFjaCByZXNwb25zZSBpcyBpbiBzZXBhcmF0ZSBjb2x1bW5zLiBIb3dldmVyIFIgcHJlZmVycyBsb25nIGZvcm1hdC4gV2UgY291bGQgYG1lbHRgIGFuZCBgY2FzdGAgd2l0aCBgcmVzaGFwZTJgIHRvIHJlc2hhcGUgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0LCBidXQgaXMgdGhlcmUgYSB3YXkgdG8gcmVzaGFwZSB1c2luZyBldmVuIGxlc3MgY29kZT8gTHVja2lseSBmb3IgdXMsIFtIYWRsZXkgV2lja2hhbV0oaHR0cHM6Ly9wcmljZW9ub21pY3MuY29tL2hhZGxleS13aWNraGFtLXRoZS1tYW4td2hvLXJldm9sdXRpb25pemVkLXIvKSBoYXMgY3JlYXRlZCB0aGUgZWFzeSB0byB1c2UgYHRpZHlyYCEgDQoNCmB0aWR5cmAgYWxsb3cgdXMgdG8gcXVpY2tseSBhbmQgZWFzaWx5IHRpZHkgYW5kIHJlb3JnYW5pemUgb3VyIGRhdGEgZm9yIGFsbCBzb3J0cyBvZiBhbmFseXNlcy4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaGVscGZ1bCB3aXRoIGEgZGlzb3JnYW5pemVkIGRhdGFzZXQuIGB0aWR5cmAgaXMgYnVpbHQgZm9yIHRoaXMgZnVuY3Rpb24sIGFuZCB0aHVzIGRvZXMgbGVzcyB0aGFuIFtyZXNoYXBlMl0oaHR0cDovL2FkZW1vcy5wZW9wbGUudWljLmVkdS9DaGFwdGVyOC5odG1sKS4gU3BlY2lmaWNhbGx5LCBgdGlkeXJgIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBleGlzaXRpbmcgZGF0YWZyYW1lcywgYW5kIGNhbm5vdCBhZ2dyZWdhdGUuDQoNCkluIHRoaXMgY2hhcHRlciwgSSB3aWxsIGdvIG92ZXIgdGhlIGhhbGxtYXJrIGZ1bmN0aW9ucyBvZiBgdGlkeXJgOiBgZ2F0aGVyKClgLCBgc2VwYXJhdGUoKWAsIGB1bml0ZSgpYCwgYW5kIGBzcHJlYWQoKWAuIA0KDQpGaXJzdCBsZXQncyBpbnN0YWxsIGFuZCBjYWxsIHVwIHRoZSBgdGlkeXJgIHBhY2thZ2UuIFdlIHdpbGwgYWxzbyBuZWVkIHRvIHVzZSB0aGUgYGRwbHlyYCBwYWNrYWdlLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXIiKSAjIEkgaGF2ZSB1c2VkICIjIiB0byAiY29tbWVudCBvdXQiIHRoaXMgbGluZSBmb3IgdGhpcyB0dXRvcmlhbC4gSnVzdCB0YWtlIGF3YXkgdGhlIGZpcnN0ICIjIiBhbmQgeW91IGFyZSBnb29kIHRvIGdvIQ0KI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikNCg0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KIyMlPiUNCldoeSBkbyB3ZSBuZWVkIGBkcGx5cmA/IGBkcGx5cmAgaXMgYSBncmFtbWFyIG9mIGRhdGEgbWFuaXB1bGF0aW9uLiBXZSBuZWVkIGBkcGx5cmAgdG8gdXNlIHRoZSBwaXBlIG9wZXJhdG9yLCBgJT4lYCwgaW4gb3VyIGNvZGUuIGAlPiVgIGlzIG5vdCByZXF1aXJlZCB0byB1c2UgdGlkeXIsIGJ1dCBpdCBkb2VzIG1ha2UgdGhpbmdzIGVhc2llciENCg0KYCU+JWAgYWxsb3dzIHlvdSB0byBwaXBlIGEgdmFsdWUgZm9yd2FyZCBpbnRvIGFuIGV4cHJlc3Npb24gb3IgdG8gZnVuY3Rpb24gY2FsbDsgc3VjaCB0aGF0IGB4ICU+JSBmYCwgaW5zdGVhZCBvZiBgZih4KWAuIFRoaXMgc2hvcnQgaGFuZCB3YXMgY3JlYXRlZCBieSBTdGVmYW4gTWlsdG9uIEJhY2hlIHdpdGggdGhlIGBtYWdyaXR0cmAgcGFja2FnZS4gVG8gcmVhZCBtb3JlIGFib3V0IHRoaXMgZnVuY3Rpb24sIGNsaWNrIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFncml0dHIvdmlnbmV0dGVzL21hZ3JpdHRyLmh0bWwpDQoNCiMjVGhlIERhdGFmcmFtZQ0KSGVyZSBJIGhhdmUgY3JlYXRlZCBhIG1lc3N5IHdpZGUgZGF0YXNldC4gRmVlbCBmcmVlIHRvIHVzZSBpdCB0byBmb2xsb3cgYWxvbmchDQoNCkluIHRoaXMgZXhhbXBsZSBzdHVkeSwgcGFydGljaXBhbnRzIHdlcmUgYXNrZWQgdG8gY2F0ZWdvcml6ZSB0aHJlZSBmYWNlcyBieSBjbGlja2luZyB2YXJpb3VzIGJ1dHRvbnMgdGhhdCByZXByZXNlbnQgdGhyZWUgZGlmZmVyZW50IGNhdGVnb3JpZXMuIFRoZSB0aW1lIGl0IHRvb2sgdG8gY2xpY2sgYSBidXR0b24gaXMgaW4gbWlsbGlzZWNvbmRzLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpuPTEwDQp3aWRlIDwtIGRhdGEuZnJhbWUoDQogIElEID0gYygxOm4pLA0KICBGYWNlLjEgPSBjKDQxMSw3MjMsMzI1LDQ1Niw1NzksNjEyLDcwOSw1MTMsNTI3LDM3OSksDQogIEZhY2UuMiA9IGMoMTIzLDMwMCw0MDAsNTAwLDYwMCw2NTQsNzg5LDkwNiw0MTMsNTY3KSwNCiAgRmFjZS4zID0gYygxNDU3LDEwMDAsNTY5LDg5Niw5NTYsMjM0NSw3ODAsNTk5LDEwMjMsNjc4KQ0KKQ0KYGBgDQoNClRoaXMgZGF0YXNldCBJIGNyZWF0ZWQgaXMgbWVzc3k7IEFzIHlvdSBjYW4gc2VlIGJlbG93LCBvbmx5IElEIGlzIGluIGEgY29sdW1uLCBSZXNwb25zZSB0aW1lIHNwbGl0IGJldHdlZW4gdGhyZWUgY29sdW1ucywgc3VjaCB0aGF0IHJlc3BvbnNlcyBhcmUgaW4gYm90aCByb3dzIGFuZCBjb2x1bW5zIChieSBJRCBhbmQgRmFjZS4xLCBGYWNlLjIsIGFuZCBGYWNlLjMpLg0KDQpXaGF0IHdlIHdhbnQgaW5zdGVhZCBpcyBvbmUgY29sdW1uIGZvciB0aGUgY29uZGl0aW9uIChGYWNlLjEsIEZhY2UuMiwgb3IgRmFjZS4zKSByZXNwb25zZXMgYW5kIGEgY29sdW1uIGZvciByZXNwb25zZSB0aW1lLCB3aXRoIGVhY2ggcm93IGJlaW5nIGEgc2luZ3VhbGFyIG9ic2VydmF0aW9uIGZvciBlYWNoIHBhcnRpY2lwYW50LiBQYXJ0aWNpcGFudCBJRHMgc2hvdWxkIHJlcGVhdCBhcyB0aGlzIGlzIGEgd2l0aGluIHN1YmplY3QgZGVzaWduIChlYWNoIHBhcnRpY2lwYW50IHNhdyBlYWNoIGZhY2UpLg0KDQpgYGAge3IsIG1lc3NhZ2U9VFJVRSwgZWNobz1GQUxTRX0NCndpZGUNCmBgYA0KDQojIEdhdGhlcigpDQpCeSB1c2luZyB0aGUgYGdhdGhlcigpYCBmdW5jdGlvbiwgd2UgY2FuIHRyYW5zZm9ybSB0aGUgZGF0YSBmcm9tIHdpZGUgdG8gbG9uZw0KSGVyZSBpcyB0aGUgZ2VuZXJpYyBjb2RlIGZvciBgZ2F0aGVyKClgOg0KDQpgYGAge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89VFJVRX0NCiNnYXRoZXIoZGF0YSwga2V5LCB2YWx1ZSwgLi4uLCBuYS5ybSA9IEZBTFNFLCBjb252ZXJ0ID0gRkFMU0UsIGZhY3Rvcl9rZXkgPSBGQUxTRSkNCmBgYA0KDQojIyBHYXRoZXIoKSBBcmd1bWVudHMNCg0KV2hvYSEgV2hhdCBkb2VzIHRoaXMgYWxsIG1lYW4/IExldCdzIGZpbmQgb3V0IG1vcmUgYWJvdXQgdGhlIGFyZ3VtZW50cyBvZiBgZ2F0aGVyKClgOg0KDQotIGBkYXRhYDoJWW91ciBkYXRhIGZyYW1lLg0KDQotIGBrZXksIHZhbHVlYDoJVGhlIHVucXVvdGVkIG5ldyBuYW1lcyBvZiBrZXkgYW5kIHZhbHVlIGNvbHVtbnMgdG8gY3JlYXRlIGluIHRoZSBvdXRwdXQuIFRoZSBrZXkgd2lsbCBiZWNvbWUgdGhlIG5hbWUgb2YgdGhlIGNvbmRpdGlvbi9JViBjb2x1bW4sIGFuZCB2YWx1ZSB3aWxsIGJlY29tZSB0aGUgbmFtZSBvZiB0aGUgcmVzcG9uc2UvRFYgY29sdW1uLg0KDQotIGAuLi5gOiBUaGUgY29sdW1ucyB0byBnYXRoZXIuIFVzZSB0aGUgZXhpc2l0aW5nIHZhcmlhYmxlIG5hbWVzLiBTZWxlY3QgYSByYW5nZSBvZiB2YXJpYWJsZXMgd2l0aCBgOmAgKGUuZy4gaWYgeW91IGhhdmUgdmFyaWFibGVzIGEsIGIsIGMsIGFuZCBkLCBhbmQgd2FudCB0byBzZWxlY3QgYWxsIG9mIHRoZXNlIHZhcmliZWxlcyB5b3Ugd2lsbCBpbmRpY2F0ZSB0aGlzIHdpdGggYTpkKS4gSWYgeW91IHdhbnQgdG8gZXhjbHVkZSBhIHZhcmlhYmxlLCB1c2UgYC1gIChlLmcuIGV4Y2x1ZGUgeSB3aXRoIC15KS4gDQoNCi0gYG5hLnJtYDogSWYgeW91IGluZGljYXRlIHRoYXQgbmEucm09VFJVRSwgdGhpcyB3aWxsIHJlbW92ZSByb3dzIGZyb20gdGhlIG91dHB1dCB3aGVyZSB0aGUgdmFsdWUgaXMgbWlzc2luZy4NCg0KLSBgY29udmVydGA6CUlmIFRSVUUgdGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgY29udmVydCB0aGUga2V5IGNvbHVtbiB0byBhIGxvZ2ljYWwsIGludGVnZXIsIG51bWVyaWMsIGNvbXBsZXgsIG9yIGZhY3RvciBhcyBhcHByb3ByaWF0ZS4gVGhpcyBpcyB1c2VmdWwgaWYgdGhlIGNvbHVtbiBuYW1lcyBhcmUgYWN0dWFsbHkgbnVtZXJpYywgaW50ZWdlciwgb3IgbG9naWNhbC4NCg0KLSBgZmFjdG9yX2tleWA6CUlmIEZBTFNFLCB0aGUgZGVmYXVsdCwgdGhlIGtleSB2YWx1ZXMgd2lsbCBiZSBzdG9yZWQgYXMgYSBjaGFyYWN0ZXIgdmVjdG9yLiBJZiBUUlVFLCB3aWxsIGJlIHN0b3JlZCBhcyBhIGZhY3Rvciwgd2hpY2ggcHJlc2VydmVzIHRoZSBvcmlnaW5hbCBvcmRlcmluZyBvZiB0aGUgY29sdW1ucy4NCg0KIyNVc2luZyBHYXRoZXIoKQ0KTm93IHRoYXQgd2UgaGF2ZSBhIGJldHRlciB1bmRlcnN0YW5kaW5nIG9mIHRoZSBhcmd1ZW1lbnRzLCBsZXRzIG1ha2Ugb3VyIGRhdGEgc2V0IGxvbmcgdXNpbmcgYGdhdGhlcigpYCENCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nIDwtIHdpZGUgJT4lIGdhdGhlcihGYWNlLCBSZXNwb25zZVRpbWUsIEZhY2UuMTpGYWNlLjMpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KbG9uZw0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlLCBub3cgd2UgaGF2ZSB0d28gY29sdW1uczogT25lIGZvciB0aGUgdGhlIEZhY2VzLCBhbmQgb25lIGZvciByZXNwb25zZSB0aW1lLiBFYWNoIHBhcnRpY2lwYW50IHNhdyBlYWNoIGZhY2UsIHNvIElEIHJlcGVhdHMgdGhyZWUgdGltZXMuIA0KDQojIFNlcGFyYXRlKCkNCg0KQWx0aG91Z2ggdGhlIGxvbmcgZGF0YXNldCB3ZSBjcmVhdGVkIHVzaW5nIGBnYXRoZXIoKWAgaXMgYWNjZXB0YWJsZSBmb3IgdXNlLCB3ZSBjYW4gYnJlYWsgZG93biB0aGUgZmFjZSB2YXJpYWJsZSBldmVuIGZ1cnRoZXIgdXNpbmcgYHNlcGFyYXRlKClgLiANCg0KSGVyZSBpcyB0aGUgZ2VuZXJpYyBjb2RlIGZvciBgc2VwYXJhdGUoKWA6DQoNCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KI3NlcGFyYXRlKGRhdGEsIGNvbCwgaW50bywgc2VwID0gIlteWzphbG51bTpdXSsiLCByZW1vdmUgPSBUUlVFLCBjb252ZXJ0ID0gRkFMU0UsIGV4dHJhID0gIndhcm4iLCBmaWxsID0gIndhcm4iKQ0KYGBgDQojI1NlcGFyYXRlKCkgQXJndW1lbnRzDQoNCldoYXQgYXJlIHRoZSBhcnVnbWVudHMgdW5pcXVlIHRvIGBzZXBhcmF0ZSgpYD8gDQoNCi0gYGNvbGA6CVVucXVvdGVkIG5hbWUgb2YgdGhlIGNvbHVtbiB0byBiZSBzZXBhcmF0ZWQuDQoNCi0gYGludG9gOiBOYW1lcyBmb3IgdGhlIG5ldyB2YXJpYWJsZXMgdGhhdCB5b3UgYXJlIHNlcGFyYXRpbmcgb3V0IGZyb20gdGhlIGNvbHVtbi4NCg0KLSBgc2VwYDogU2VwYXJhdG9yIGJldHdlZW4gY29sdW1ucy4gSWYgdGhlIHNlcHJhdG9yIGlzIGEgY2hhcmFjdGVyLCBpdCBpcyBpbnRlcnByZXRlZCBhcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCBtYXRjaGVzIGFueSBzZXF1ZW5jZSBvZiBub24tYWxwaGFudW1lcmljIHZhbHVlcy4gSW4gdGhlIGV4YW1wbGUsIGVhY2ggZmFjZSBpcyBpbmRpY2F0ZWQgYnkgYSBudW1iZXIgdGhhdCBmb2xsb3dzIGEgcGVyaW9kIChgLmApLiBJIGRvIG5vdCBuZWVkIHNwZWlmY3kgdGhpcyBiZWNhdXNlIHRoaXMgZXhpc3RzIGluIGVhY2ggbGV2ZWwgb2YgRmFjZS4gSWYgbnVtZXJpYywgaXQgaXMgaW50ZXJwcmV0ZWQgYXMgdGhlIHBvc2l0aW9uIHRvIHNwbGl0IGF0LiBQb3NpdGl2ZSB2YWx1ZXMgc3RhcnQgYXQgMSBhdCB0aGUgZmFyLWxlZnQgb2YgdGhlIHN0cmluZzsgbmVnYXRpdmUgdmFsdWUgc3RhcnQgYXQgLTEgYXQgdGhlIGZhci1yaWdodCBvZiB0aGUgc3RyaW5nLiBUaGUgbGVuZ3RoIG9mIGBzZXBgIHNob3VsZCBiZSBvbmUgbGVzcyB0aGFuIGBpbnRvYC4NCg0KLSBgcmVtb3ZlYDoJSWYgdGhpcyBpcyBUUlVFLCBpdCByZW1vdmVzIHRoZSBpbnB1dCBjb2x1bW4gZnJvbSBvdXRwdXQgZGF0YSBmcmFtZS4NCg0KLSBgZXh0cmFgOiBJZiBgc2VwYCBpcyBhIGNoYXJhY3RlciB2ZWN0b3IgKGxpa2UgYC5gKSwgdGhpcyBjb250cm9scyB3aGF0IGhhcHBlbnMgd2hlbiB0aGVyZSBhcmUgdG9vIG1hbnkgcGllY2VzIChlLmcuIEZhY2UuMS5BLCByYXRoZXIgdGhhbiBGYWNlLjEpLiBUaGVyZSBhcmUgdGhyZWUgdmFsaWQgb3B0aW9uczoNCiJ3YXJuIiAodGhlIGRlZmF1bHQpOiBlbWl0IGEgd2FybmluZyBhbmQgZHJvcCBleHRyYSB2YWx1ZXMuDQoiZHJvcCI6IGRyb3AgYW55IGV4dHJhIHZhbHVlcyB3aXRob3V0IGEgd2FybmluZy4NCiJtZXJnZSI6IG9ubHkgc3BsaXRzIGF0IG1vc3QgbGVuZ3RoKGludG8pIHRpbWVzDQoNCi0gYGZpbGxgOgkgSWYgYHNlcGAgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIChsaWtlIGAuYCksIHRoaXMgY29udHJvbHMgd2hhdCBoYXBwZW5zIHdoZW4gdGhlcmUgYXJlIG5vdCBlbm91Z2ggcGllY2VzIChlLmcuIEZhY2UxLCByYXRoZXIgdGhhbiBGYWNlLjEpLiBUaGVyZSBhcmUgdGhyZWUgdmFsaWQgb3B0aW9uczoNCiJ3YXJuIiAodGhlIGRlZmF1bHQpOiBlbWl0IGEgd2FybmluZyBhbmQgZmlsbCBmcm9tIHRoZSByaWdodA0KInJpZ2h0IjogZmlsbCB3aXRoIG1pc3NpbmcgdmFsdWVzIG9uIHRoZSByaWdodA0KImxlZnQiOiBmaWxsIHdpdGggbWlzc2luZyB2YWx1ZXMgb24gdGhlIGxlZnQNCg0KIyNVc2luZyBTZXBhcmF0ZSgpDQoNCkVhY2ggZmFjZSBpcyBpbmRpY2F0ZWQgYnkgbnVtYmVyIGFmdGVyIGEgcGVyaW9kLiBUaGlzIHZhcmlhYmxlIGFubm90YXRpb24gYWxsb3dzIHVzIHRvIHNlcGFyYXRlIHRoZSBmYWNlIHZhcmlhYmxlIGludG8gdHdvLiBCeSB1c2luZyB0aGUgYHNlcGFyYXRlYCBmdW5jdGlvbiBvZiBgdGlkeXJgIHdlIGNhbiB0ZWFzZSBhcGFydCBzaW5nbGUgdmFyaWFibGVzIHdoaWNoIHNvbWV0aW1lcyBjYXB0dXJlIG11bHRpcGxlIHZhcmlhYmxlcyAob3Igc29tZXRpbWVzIHJlZHVuZGFudCBpbmZvcm1hdGlvbikuIA0KDQpJbiB0aGlzIGNhc2UsIEkgd2FudCB0byBzcGxpdCB0aGUgRmFjZSBmcm9tIHRoZSBudW1iZXIgYXR0YWNoZWQgdG8gaXQsIHdoaWNoIGluIHRoaXMgZXhhbXBsZSByZXByZXNlbnRzIHRoZSByYWNlIG9mIHRoZSBmYWNlLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nX3NlcGFyYXRlIDwtIGxvbmcgJT4lIHNlcGFyYXRlKEZhY2UsIGMoIlRhcmdldCIsICJOdW1iZXIiKSkNCmBgYA0KYGBgIHtyLCBtZXNzYWdlPVRSVUUsIGVjaG89RkFMU0V9DQpsb25nX3NlcGFyYXRlDQpgYGANCk5vdywgV2UgaGF2ZSB0d28gY29sdW1ucywgb25lIGZvciBUYXJnZXQsIHRoZSB2YWx1ZXMgb2Ygd2hpY2ggYXJlIGFsbCAiRmFjZSIsIGFuZCBvbmUgZm9yIE51bWJlciwgd2hpY2ggaW5kaWNhdGVzIHdoaWNoIG9mIHRoZSB0aHJlZSBmYWNlcyBpdCBpcy4gDQoNCiMgVW5pdGUNClRvIHVuZG8gYHNlcGFyYXRlKClgLCB3ZSBjYW4gdXNlIGB1bml0ZSgpYCwgd2hpY2ggbWVyZ2VzIHR3byB2YXJpYWJsZXMgaW50byBvbmUuIA0KDQpIZXJlIGlzIHRoZSBnZW5lcmljIGNvZGUgZm9yIGB1bml0ZSgpYDoNCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQojdW5pdGUoZGF0YSwgY29sLCAuLi4sIHNlcCA9ICIuIiwgcmVtb3ZlID0gVFJVRSkNCmBgYA0KDQojI1VuaXRlKCkgQXJndW1lbnRzDQoNCkhlcmUgYXJlIHRoZSBhcnVnbWVudHMgdW5pcXVlIHRvIGB1bml0ZSgpYDogDQoNCi0gYHNlcGA6IEluIHRoZSBjb2RlIGZvciBgdW5pdGUoKWAgdGhlIGBzZXBgIGluZGljYXRlZCB0aGUgc2VwYXJhdG9yIHdlIGNob29zZSB0byB0byB1c2UgdG8gYmluZCB2YWx1ZXMuIEluIHRoaXMgY2FzZSwgd2UgYXJlIHVzaW5nIGAuYA0KDQojI1VzaW5nIFVuaXRlKCkNCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nX3VuaXRlIDwtIGxvbmdfc2VwYXJhdGUgJT4lIHVuaXRlKEZhY2UsIFRhcmdldCwgTnVtYmVyLCBzZXAgPSAiLiIpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KbG9uZ191bml0ZQ0KYGBgDQpBcyB5b3UgY2FuIHNlZSB0aGUgZGF0YSBub3cgbG9va3MgbGlrZSBpdCBkaWQgd2hlbiB3ZSBmaXJzdCB0cmFuc2Zyb21lZCBmcm9tIHdpZGUgdG8gbG9uZyB1c2luZyBgZ2F0aGVyKClgIQ0KDQojIFNwcmVhZA0KRmluYWxseSwgd2Ugd2lsbCB0cmFuc2Zvcm0gdGhlIGRhdGEgZnJvbSBsb25nIGJhY2sgdG8gd2lkZSB3aXRoIHRoZSBgc3ByZWFkKClgIGZ1bmN0aW9uLg0KDQpIZXJlIGlzIHRoZSBnZW5lcmljIGNvZGUgZm9yIGBzcHJlYWQoKWANCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KI3NwcmVhZChkYXRhLCBrZXksIHZhbHVlLCBmaWxsID0gTkEsIGNvbnZlcnQgPSBGQUxTRSwgZHJvcCA9IFRSVUUsIHNlcCA9IE5VTEwpDQpgYGANCg0KIyNTcHJlYWQoKSBBcmd1bWVudHMNCg0KVGhlIGFydWdtZW50cyB1bmlxdWUgdG8gYHNwcmVhZCgpYDoNCg0KLSBga2V5YDoJVGhlIHVucXVvdGVkIG5hbWUgb2YgdGhlIGNvbHVtbiB3aG9zZSB2YWx1ZXMgd2lsbCBiZSB1c2VkIGFzIGNvbHVtbiBoZWFkaW5ncy4NCg0KLSBgdmFsdWVgOglUaGUgdW5xdW90ZWQgbmFtZSBvZiB0aGUgY29sdW1uIHdob3NlIHZhbHVlcyB3aWxsIHBvcHVsYXRlIHRoZSBjZWxscy4gDQoNCi0gYGZpbGxgOglJZiB1c2VkLCBtaXNzaW5nIHZhbHVlcyB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhpcyB2YWx1ZS4gVGhlcmUgYXJlIHR3byB0eXBlcyBvZiBtaXNzaW5nIGluIHRoZSBpbnB1dDogZXhwbGljaXQgbWlzc2luZyB2YWx1ZXMgKGkuZS4gYE5BYCksIGFuZCBpbXBsaWNpdCBtaXNzaW5ncywgcm93cyB0aGF0IHNpbXBseSBhcmVuJ3QgcHJlc2VudC4gQm90aCB0eXBlcyBvZiBtaXNzaW5nIHZhbHVlIHdpbGwgYmUgcmVwbGFjZWQgYnkgYGZpbGxgLg0KDQotIGBjb252ZXJ0YDogSWYgYFRSVUVgLCB0aGlzIHdpbGwgYXV0b21hdGljYWxseSBjb252ZXJ0IHRoZSBuZXcgY29sdW1ucyB0byBhIGxvZ2ljYWwsIGludGVnZXIsIG51bWVyaWMsIGNvbXBsZXgsIG9yIGZhY3RvciBhcyBhcHByb3ByaWF0ZS4NCg0KLSBgZHJvcGA6IElmIGBGQUxTRWAsIHdpbGwga2VlcCBmYWN0b3IgbGV2ZWxzIHRoYXQgZG9uJ3QgYXBwZWFyIGluIHRoZSBkYXRhLCBmaWxsaW5nIGluIG1pc3NpbmcgY29tYmluYXRpb25zIHdpdGggYGZpbGxgLg0KDQotIGBzZXBgOiBJZiBgTlVMTGAsIHRoZSBjb2x1bW4gbmFtZXMgd2lsbCBiZSB0YWtlbiBmcm9tIHRoZSB2YWx1ZXMgb2Yga2V5IHZhcmlhYmxlLiBJZiBub24tYE5VTExgLCB0aGUgY29sdW1uIG5hbWVzIHdpbGwgYmUgY3JlYXRlZCBieSBzdHJpbmdpbmcgdG9nZXRoZXIgdGhlIG5hbWUsIHNlcGFyYXRvciwgYW5kIHZhbHVlLg0KDQoNCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KYmFja190b193aWRlIDwtIGxvbmdfdW5pdGUgJT4lIHNwcmVhZChGYWNlLCBSZXNwb25zZVRpbWUpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KYmFja190b193aWRlDQpgYGANCg0KQW5kIHRoZXJlIHdlIGhhdmUgaXQhIFdlIGhhdmUgY29tZSBmdWxsIGNpcmNsZSBiYWNrIGludG8gd2lkZS4gDQoNCiNSZWZlcmVuY2VzDQpodHRwczovL3ByaWNlb25vbWljcy5jb20vaGFkbGV5LXdpY2toYW0tdGhlLW1hbi13aG8tcmV2b2x1dGlvbml6ZWQtci8gIyBXaG8gaXMgdGhpcyBIYWRsZXkgV2lja2hhbSBndXk/DQoNCmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCAjIEZ1cnRoZXIgcmVhZGluZyBhYm91dCBgJT4lYA0KDQpodHRwczovL2Jsb2cucnN0dWRpby5vcmcvMjAxNC8wNy8yMi9pbnRyb2R1Y2luZy10aWR5ci8gIyBIZWxwZnVsIG92ZXJ2aWV3IG9mIHRpZHlyDQoNCmh0dHA6Ly9hZGVtb3MucGVvcGxlLnVpYy5lZHUvQ2hhcHRlcjguaHRtbCAjIFRpbSBDYXJzZWwncyBjaGFwdGVyIG9uIHJlc2hhcGUyDQoNCmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90aWR5ci90aWR5ci5wZGYgIyBBIGZ1bGwgZ3VpZGUgb2YgdGlkeSByIGFuZCBhbGwgdGhlIGFyZ3VtZW50cyBmb3IgZWFjaCBmdW5jdGlvbiBvZiB0aGUgcGFja2FnZQ0KDQpodHRwOi8vZ2FycmV0dGdtYW4uZ2l0aHViLmlvL3RpZHlpbmcvICMgRGlmZmVyZW50IHR5cGVzIG9mIG1lc3N5IGRhdGEgYW5kIGhvdyB0byBmaXggd2l0aCB0aWR5cg0KDQo8c2NyaXB0Pg0KICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7DQogIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLA0KICBtPXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUobylbMF07YS5hc3luYz0xO2Euc3JjPWc7bS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShhLG0pDQogIH0pKHdpbmRvdyxkb2N1bWVudCwnc2NyaXB0JywnaHR0cHM6Ly93d3cuZ29vZ2xlLWFuYWx5dGljcy5jb20vYW5hbHl0aWNzLmpzJywnZ2EnKTsNCg0KICBnYSgnY3JlYXRlJywgJ1VBLTk4ODc4NzkzLTEnLCAnYXV0bycpOw0KICBnYSgnc2VuZCcsICdwYWdldmlldycpOw0KDQo8L3NjcmlwdD4NCg==