In our research, we often need information from multiple data sets, and we need to merge those data sets into one data frame for future analysis. For example, when we replicate one of Inglehart’s research questions on whether regime type influences the mass support for democracy, the information we interested in are in three different data sets: the world value survey (WVS), the European Value Study(EVS), and the Freedom House Score. The WVS and EVS data each contains public opinion data of a subset of countries in the world. Combining these two would give us a larger sample of countries. The Freedom House data contains the regime types.

To answer Inglehart’s research question, we want to have a merged data frame with country names, citizens’ opinion towards democracy in each country, and each country’s corresponding regime type. We will practice merging data vertically and horizontally in this example.

1 Load the data sets

library(openxlsx) 
WVS <- read.xlsx("WVS5.xlsx")
EVS <- read.xlsx("EVS2008.xlsx")
FH <- read.xlsx("FreedomHouse2017.xlsx")
# View and get familar with the date sets you will be using
dim(WVS)
dim(EVS)
dim(FH)
names(WVS)
names(EVS)
names(FH)
summary(WVS)
summary(EVS)
summary(FH)

2 Merge Vertically (add rows/observations)

Merging data vertically means that we add more observations to the current data. In other words, we stack two data sets. In our case, we want to merge the WVS data and EVS data vertically, because these two data sets contain the same variables but with different observations (countries). We can use the function rbind() to add the new data to the current turnout data (merge them vertically). You should be carefully about the variable names and order in the new data set. The names and order of the variable of the second data set should match exactly with the first one.

2.1 View the names of the data sets that you want to stack

names(WVS)
names(EVS)

We can see that EVS contains one extra variable: “Country_Abrv”. The order of the rest variables are the same but with slightly different names. We need to fix these two problems in the next step.

2.2 Fix any variables that do not match

#delete the first collum of EVS, the extra variable that we are not gonna use
EVS <- EVS[,-1]
#change variable names in WVS to match EVS
names(WVS)<-names(EVS)
#before you merge, examine the two datasets again to make sure that they have the same variables and variable names 
names(WVS)
names(EVS)
#you can also use set operation to check are there any variable names of WVS that is not in the names of EVS, vice versa:
setdiff(names(WVS),names(EVS))

2.3 Check whether there are overlapping observations

#Intersection returns the observations appeared in both variables
intersect(WVS$Country,EVS$Country)
#Alternatively you can also use is.element function, which is also a set operation. It returns logic values showing whether the observation in X variable also appears in the Y variable
is.element(WVS$Country,EVS$Country)

There are 20 observations appeared in both data set. We need to delete the extra entries (in one of the data set):

WVS.unique <- WVS[-which(is.element(WVS$Country,EVS$Country)),]
# Double check 
dim(WVS.unique) # We should have deleted 20 observations and kept all the variables. The correct observations should be 56-20 = 36.

2.4 Check whether the variables are on the same scale

In fact if you check closely in the beginning of this document when we load and summarize the data, you should already notice that the variables are not on the same scale: EVS is the percentage.

summary(WVS.unique)
summary(EVS)

2.5 Convert one of the data to be on the same scale

WVS.unique[,c(2:9)] <- WVS.unique[,c(2:9)]*100
#check again
summary(WVS.unique)

2.6 Stack WVS and EVS, create a new dataframe

PublicOpinion <- rbind(WVS.unique,EVS)
# Double check
dim(PublicOpinion) # 46 + 36
summary(PublicOpinion)

3 Merge horizontally (add columns/variables)

Now we want to merge the PublicOpion data we just created with the Freedom house score. You can consider the horizontal merging as adding variables to the data, or adding additional characteristics/information about each country in this case. To merge data this way, the new data you want to merge/add to the current data must share at least one variable with the current data for r to match observations. In our example, we want to match the two data sets by country name.

#check the variable name for country. In our example, the two data sets happen to have the same variable name of the country variable.
names(FH)
names(PublicOpinion)
#Check how many countries each data have
length(FH$Country)
length(PublicOpinion$Country)

3.1 Merge Data

#Merge by country name 
merged.all <- merge(PublicOpinion,FH,by="Country",
                all = TRUE) # Keep all the unique country names
merged.intersect <- merge(PublicOpinion,FH,by="Country",
                all = FALSE) # Only merge and return countries that appear in both data sets
merged.x <- merge(PublicOpinion,FH,by="Country",
                all.x = TRUE) # Keep all the countries in data X, the PublicOpinion data in the example
merged.y <- merge(PublicOpinion,FH,by="Country",
                all.y = TRUE) # Keep all the countries in data Y, the Freedom House score

#If the Index variable has different names in the two datasets, you can do
merged.a <- merge(PublicOpinion,FH,
                  by.x="Country",by.y="Country", 
                all = TRUE)

#Check the merged data
dim(merged.all)
dim(merged.both)
dim(merged.x) # should match the number of observation in PublicOpinion
dim(merged.y) # should match the number of observation in FH

3.2 Diagnostic

Each of the two data sets contains country names that are not in the other data set. There are two possible reasons: 1) some countries are missing in either one of them; 2) some countries are spelled differently

setdiff(PublicOpinion$Country,FH$Country)

# Change those country names that are spelled differently 
library(car)
PublicOpinion$Country<-recode(PublicOpinion$Country,"'Argenti'='Argentina';'BurkiFaso'='Burkina Faso';'Chi'='China';'GreatBritain'='United Kingdom';'NewZealand'='New Zealand';'SouthAfrica'='South Africa';'SouthKorea'='South Korea';'TrinidadandTobago'='Trinidad and Tobago';'UnitedStates'='United States of America';'Vietm'='Vietnam'")

#Check whether there are countries appeared more than once
length(unique(PublicOpinion$Country))
table(PublicOpinion$Country)[which(table(PublicOpinion$Country)>1)] 
#Delete the extra entry

PublicOpinion<-PublicOpinion[-which(PublicOpinion$Country=="United Kingdom")[1],]

3.3 Merge Data

merged <- merge(PublicOpinion,FH,by="Country",
                all.x = TRUE)
#Check whether you have succeed
dim(PublicOpinion)
dim(merged)  # The merged data should have the same number of observations as in PublicOpinion, because we set all.x = TRUE. We set the merge function to include all the variable in X dataframe. 

Helpsheet made for PLSC 309 by Yaoyao Dai

LS0tCnRpdGxlOiAiTWVyZ2UgRGF0YSBpbiBSIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0aGVtZTogY2VydWxlYW4KICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQogICAgdG9jOiBUUlVFCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogVFJVRQotLS0KCioqKgpJbiBvdXIgcmVzZWFyY2gsIHdlIG9mdGVuIG5lZWQgaW5mb3JtYXRpb24gZnJvbSBtdWx0aXBsZSBkYXRhIHNldHMsIGFuZCB3ZSBuZWVkIHRvIG1lcmdlIHRob3NlIGRhdGEgc2V0cyBpbnRvIG9uZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgYW5hbHlzaXMuIEZvciBleGFtcGxlLCB3aGVuIHdlIHJlcGxpY2F0ZSBvbmUgb2YgSW5nbGVoYXJ0J3MgcmVzZWFyY2ggcXVlc3Rpb25zIG9uIHdoZXRoZXIgcmVnaW1lIHR5cGUgaW5mbHVlbmNlcyB0aGUgbWFzcyBzdXBwb3J0IGZvciBkZW1vY3JhY3ksIHRoZSBpbmZvcm1hdGlvbiB3ZSBpbnRlcmVzdGVkIGluIGFyZSBpbiB0aHJlZSBkaWZmZXJlbnQgZGF0YSBzZXRzOiB0aGUgd29ybGQgdmFsdWUgc3VydmV5IChXVlMpLCB0aGUgRXVyb3BlYW4gVmFsdWUgU3R1ZHkoRVZTKSwgYW5kIHRoZSBGcmVlZG9tIEhvdXNlIFNjb3JlLiBUaGUgV1ZTIGFuZCBFVlMgZGF0YSBlYWNoIGNvbnRhaW5zIHB1YmxpYyBvcGluaW9uIGRhdGEgb2YgYSBzdWJzZXQgb2YgY291bnRyaWVzIGluIHRoZSB3b3JsZC4gQ29tYmluaW5nIHRoZXNlIHR3byB3b3VsZCBnaXZlIHVzIGEgbGFyZ2VyIHNhbXBsZSBvZiBjb3VudHJpZXMuIFRoZSBGcmVlZG9tIEhvdXNlIGRhdGEgY29udGFpbnMgdGhlIHJlZ2ltZSB0eXBlcy4gCgpUbyBhbnN3ZXIgSW5nbGVoYXJ0J3MgcmVzZWFyY2ggcXVlc3Rpb24sIHdlIHdhbnQgdG8gaGF2ZSBhIG1lcmdlZCBkYXRhIGZyYW1lIHdpdGggY291bnRyeSBuYW1lcywgY2l0aXplbnMnIG9waW5pb24gdG93YXJkcyBkZW1vY3JhY3kgaW4gZWFjaCBjb3VudHJ5LCBhbmQgZWFjaCBjb3VudHJ5J3MgY29ycmVzcG9uZGluZyByZWdpbWUgdHlwZS4gV2Ugd2lsbCBwcmFjdGljZSBtZXJnaW5nIGRhdGEgdmVydGljYWxseSBhbmQgaG9yaXpvbnRhbGx5IGluIHRoaXMgZXhhbXBsZS4KCiMgTG9hZCB0aGUgZGF0YSBzZXRzCgpgYGB7cn0KbGlicmFyeShvcGVueGxzeCkgCldWUyA8LSByZWFkLnhsc3goIldWUzUueGxzeCIpCkVWUyA8LSByZWFkLnhsc3goIkVWUzIwMDgueGxzeCIpCkZIIDwtIHJlYWQueGxzeCgiRnJlZWRvbUhvdXNlMjAxNy54bHN4IikKYGBgCgpgYGB7cn0KIyBWaWV3IGFuZCBnZXQgZmFtaWxhciB3aXRoIHRoZSBkYXRlIHNldHMgeW91IHdpbGwgYmUgdXNpbmcKZGltKFdWUykKZGltKEVWUykKZGltKEZIKQpuYW1lcyhXVlMpCm5hbWVzKEVWUykKbmFtZXMoRkgpCnN1bW1hcnkoV1ZTKQpzdW1tYXJ5KEVWUykKc3VtbWFyeShGSCkKYGBgCgojIE1lcmdlIFZlcnRpY2FsbHkgKGFkZCByb3dzL29ic2VydmF0aW9ucykKCk1lcmdpbmcgZGF0YSB2ZXJ0aWNhbGx5IG1lYW5zIHRoYXQgd2UgYWRkIG1vcmUgb2JzZXJ2YXRpb25zIHRvIHRoZSBjdXJyZW50IGRhdGEuIEluIG90aGVyIHdvcmRzLCB3ZSBzdGFjayB0d28gZGF0YSBzZXRzLiBJbiBvdXIgY2FzZSwgd2Ugd2FudCB0byBtZXJnZSB0aGUgV1ZTIGRhdGEgYW5kIEVWUyBkYXRhIHZlcnRpY2FsbHksIGJlY2F1c2UgdGhlc2UgdHdvIGRhdGEgc2V0cyBjb250YWluIHRoZSBzYW1lIHZhcmlhYmxlcyBidXQgd2l0aCBkaWZmZXJlbnQgb2JzZXJ2YXRpb25zIChjb3VudHJpZXMpLiBXZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiByYmluZCgpIHRvIGFkZCB0aGUgbmV3IGRhdGEgdG8gdGhlIGN1cnJlbnQgdHVybm91dCBkYXRhIChtZXJnZSB0aGVtIHZlcnRpY2FsbHkpLiBZb3Ugc2hvdWxkIGJlIGNhcmVmdWxseSBhYm91dCB0aGUgdmFyaWFibGUgbmFtZXMgYW5kIG9yZGVyIGluIHRoZSBuZXcgZGF0YSBzZXQuIFRoZSBuYW1lcyBhbmQgb3JkZXIgb2YgdGhlIHZhcmlhYmxlIG9mIHRoZSBzZWNvbmQgZGF0YSBzZXQgc2hvdWxkIG1hdGNoIGV4YWN0bHkgd2l0aCB0aGUgZmlyc3Qgb25lLgoKIyNWaWV3IHRoZSBuYW1lcyBvZiB0aGUgZGF0YSBzZXRzIHRoYXQgeW91IHdhbnQgdG8gc3RhY2sKYGBge3J9Cm5hbWVzKFdWUykKbmFtZXMoRVZTKQpgYGAKV2UgY2FuIHNlZSB0aGF0IEVWUyBjb250YWlucyBvbmUgZXh0cmEgdmFyaWFibGU6ICJDb3VudHJ5X0FicnYiLiBUaGUgb3JkZXIgb2YgdGhlIHJlc3QgdmFyaWFibGVzIGFyZSB0aGUgc2FtZSBidXQgd2l0aCBzbGlnaHRseSBkaWZmZXJlbnQgbmFtZXMuIFdlIG5lZWQgdG8gZml4IHRoZXNlIHR3byBwcm9ibGVtcyBpbiB0aGUgbmV4dCBzdGVwLgoKIyNGaXggYW55IHZhcmlhYmxlcyB0aGF0IGRvIG5vdCBtYXRjaCAKYGBge3J9CiNkZWxldGUgdGhlIGZpcnN0IGNvbGx1bSBvZiBFVlMsIHRoZSBleHRyYSB2YXJpYWJsZSB0aGF0IHdlIGFyZSBub3QgZ29ubmEgdXNlCkVWUyA8LSBFVlNbLC0xXQojY2hhbmdlIHZhcmlhYmxlIG5hbWVzIGluIFdWUyB0byBtYXRjaCBFVlMKbmFtZXMoV1ZTKTwtbmFtZXMoRVZTKQojYmVmb3JlIHlvdSBtZXJnZSwgZXhhbWluZSB0aGUgdHdvIGRhdGFzZXRzIGFnYWluIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZXkgaGF2ZSB0aGUgc2FtZSB2YXJpYWJsZXMgYW5kIHZhcmlhYmxlIG5hbWVzIApuYW1lcyhXVlMpCm5hbWVzKEVWUykKI3lvdSBjYW4gYWxzbyB1c2Ugc2V0IG9wZXJhdGlvbiB0byBjaGVjayBhcmUgdGhlcmUgYW55IHZhcmlhYmxlIG5hbWVzIG9mIFdWUyB0aGF0IGlzIG5vdCBpbiB0aGUgbmFtZXMgb2YgRVZTLCB2aWNlIHZlcnNhOgpzZXRkaWZmKG5hbWVzKFdWUyksbmFtZXMoRVZTKSkKYGBgCgojI0NoZWNrIHdoZXRoZXIgdGhlcmUgYXJlIG92ZXJsYXBwaW5nIG9ic2VydmF0aW9ucwpgYGB7cn0KI0ludGVyc2VjdGlvbiByZXR1cm5zIHRoZSBvYnNlcnZhdGlvbnMgYXBwZWFyZWQgaW4gYm90aCB2YXJpYWJsZXMKaW50ZXJzZWN0KFdWUyRDb3VudHJ5LEVWUyRDb3VudHJ5KQojQWx0ZXJuYXRpdmVseSB5b3UgY2FuIGFsc28gdXNlIGlzLmVsZW1lbnQgZnVuY3Rpb24sIHdoaWNoIGlzIGFsc28gYSBzZXQgb3BlcmF0aW9uLiBJdCByZXR1cm5zIGxvZ2ljIHZhbHVlcyBzaG93aW5nIHdoZXRoZXIgdGhlIG9ic2VydmF0aW9uIGluIFggdmFyaWFibGUgYWxzbyBhcHBlYXJzIGluIHRoZSBZIHZhcmlhYmxlCmlzLmVsZW1lbnQoV1ZTJENvdW50cnksRVZTJENvdW50cnkpCmBgYApUaGVyZSBhcmUgMjAgb2JzZXJ2YXRpb25zIGFwcGVhcmVkIGluIGJvdGggZGF0YSBzZXQuIFdlIG5lZWQgdG8gZGVsZXRlIHRoZSBleHRyYSBlbnRyaWVzIChpbiBvbmUgb2YgdGhlIGRhdGEgc2V0KToKYGBge3J9CldWUy51bmlxdWUgPC0gV1ZTWy13aGljaChpcy5lbGVtZW50KFdWUyRDb3VudHJ5LEVWUyRDb3VudHJ5KSksXQojIERvdWJsZSBjaGVjayAKZGltKFdWUy51bmlxdWUpICMgV2Ugc2hvdWxkIGhhdmUgZGVsZXRlZCAyMCBvYnNlcnZhdGlvbnMgYW5kIGtlcHQgYWxsIHRoZSB2YXJpYWJsZXMuIFRoZSBjb3JyZWN0IG9ic2VydmF0aW9ucyBzaG91bGQgYmUgNTYtMjAgPSAzNi4KYGBgCgojI0NoZWNrIHdoZXRoZXIgdGhlIHZhcmlhYmxlcyBhcmUgb24gdGhlIHNhbWUgc2NhbGUgCgpJbiBmYWN0IGlmIHlvdSBjaGVjayBjbG9zZWx5IGluIHRoZSBiZWdpbm5pbmcgb2YgdGhpcyBkb2N1bWVudCB3aGVuIHdlIGxvYWQgYW5kIHN1bW1hcml6ZSB0aGUgZGF0YSwgeW91IHNob3VsZCBhbHJlYWR5IG5vdGljZSB0aGF0IHRoZSB2YXJpYWJsZXMgYXJlIG5vdCBvbiB0aGUgc2FtZSBzY2FsZTogRVZTIGlzIHRoZSBwZXJjZW50YWdlLiAKCmBgYHtyfQpzdW1tYXJ5KFdWUy51bmlxdWUpCnN1bW1hcnkoRVZTKQpgYGAKCiMjQ29udmVydCBvbmUgb2YgdGhlIGRhdGEgdG8gYmUgb24gdGhlIHNhbWUgc2NhbGUKYGBge3J9CldWUy51bmlxdWVbLGMoMjo5KV0gPC0gV1ZTLnVuaXF1ZVssYygyOjkpXSoxMDAKI2NoZWNrIGFnYWluCnN1bW1hcnkoV1ZTLnVuaXF1ZSkKYGBgCgoKIyNTdGFjayBXVlMgYW5kIEVWUywgY3JlYXRlIGEgbmV3IGRhdGFmcmFtZQpgYGB7cn0KUHVibGljT3BpbmlvbiA8LSByYmluZChXVlMudW5pcXVlLEVWUykKIyBEb3VibGUgY2hlY2sKZGltKFB1YmxpY09waW5pb24pICMgNDYgKyAzNgpzdW1tYXJ5KFB1YmxpY09waW5pb24pCmBgYAoKIyBNZXJnZSBob3Jpem9udGFsbHkgKGFkZCBjb2x1bW5zL3ZhcmlhYmxlcykKCk5vdyB3ZSB3YW50IHRvIG1lcmdlIHRoZSBQdWJsaWNPcGlvbiBkYXRhIHdlIGp1c3QgY3JlYXRlZCB3aXRoIHRoZSBGcmVlZG9tIGhvdXNlIHNjb3JlLiBZb3UgY2FuIGNvbnNpZGVyIHRoZSBob3Jpem9udGFsIG1lcmdpbmcgYXMgYWRkaW5nIHZhcmlhYmxlcyB0byB0aGUgZGF0YSwgb3IgYWRkaW5nIGFkZGl0aW9uYWwgY2hhcmFjdGVyaXN0aWNzL2luZm9ybWF0aW9uIGFib3V0IGVhY2ggY291bnRyeSBpbiB0aGlzIGNhc2UuIFRvIG1lcmdlIGRhdGEgdGhpcyB3YXksIHRoZSBuZXcgZGF0YSB5b3Ugd2FudCB0byBtZXJnZS9hZGQgdG8gdGhlIGN1cnJlbnQgZGF0YSBtdXN0IHNoYXJlIGF0IGxlYXN0IG9uZSB2YXJpYWJsZSB3aXRoIHRoZSBjdXJyZW50IGRhdGEgZm9yIHIgdG8gbWF0Y2ggb2JzZXJ2YXRpb25zLiBJbiBvdXIgZXhhbXBsZSwgd2Ugd2FudCB0byBtYXRjaCB0aGUgdHdvIGRhdGEgc2V0cyBieSBjb3VudHJ5IG5hbWUuIAoKYGBge3J9CiNjaGVjayB0aGUgdmFyaWFibGUgbmFtZSBmb3IgY291bnRyeS4gSW4gb3VyIGV4YW1wbGUsIHRoZSB0d28gZGF0YSBzZXRzIGhhcHBlbiB0byBoYXZlIHRoZSBzYW1lIHZhcmlhYmxlIG5hbWUgb2YgdGhlIGNvdW50cnkgdmFyaWFibGUuCm5hbWVzKEZIKQpuYW1lcyhQdWJsaWNPcGluaW9uKQojQ2hlY2sgaG93IG1hbnkgY291bnRyaWVzIGVhY2ggZGF0YSBoYXZlCmxlbmd0aChGSCRDb3VudHJ5KQpsZW5ndGgoUHVibGljT3BpbmlvbiRDb3VudHJ5KQpgYGAKCiMjTWVyZ2UgRGF0YQpgYGB7cn0KI01lcmdlIGJ5IGNvdW50cnkgbmFtZSAKbWVyZ2VkLmFsbCA8LSBtZXJnZShQdWJsaWNPcGluaW9uLEZILGJ5PSJDb3VudHJ5IiwKICAgICAgICAgICAgICAgIGFsbCA9IFRSVUUpICMgS2VlcCBhbGwgdGhlIHVuaXF1ZSBjb3VudHJ5IG5hbWVzCm1lcmdlZC5pbnRlcnNlY3QgPC0gbWVyZ2UoUHVibGljT3BpbmlvbixGSCxieT0iQ291bnRyeSIsCiAgICAgICAgICAgICAgICBhbGwgPSBGQUxTRSkgIyBPbmx5IG1lcmdlIGFuZCByZXR1cm4gY291bnRyaWVzIHRoYXQgYXBwZWFyIGluIGJvdGggZGF0YSBzZXRzCm1lcmdlZC54IDwtIG1lcmdlKFB1YmxpY09waW5pb24sRkgsYnk9IkNvdW50cnkiLAogICAgICAgICAgICAgICAgYWxsLnggPSBUUlVFKSAjIEtlZXAgYWxsIHRoZSBjb3VudHJpZXMgaW4gZGF0YSBYLCB0aGUgUHVibGljT3BpbmlvbiBkYXRhIGluIHRoZSBleGFtcGxlCm1lcmdlZC55IDwtIG1lcmdlKFB1YmxpY09waW5pb24sRkgsYnk9IkNvdW50cnkiLAogICAgICAgICAgICAgICAgYWxsLnkgPSBUUlVFKSAjIEtlZXAgYWxsIHRoZSBjb3VudHJpZXMgaW4gZGF0YSBZLCB0aGUgRnJlZWRvbSBIb3VzZSBzY29yZQoKI0lmIHRoZSBJbmRleCB2YXJpYWJsZSBoYXMgZGlmZmVyZW50IG5hbWVzIGluIHRoZSB0d28gZGF0YXNldHMsIHlvdSBjYW4gZG8KbWVyZ2VkLmEgPC0gbWVyZ2UoUHVibGljT3BpbmlvbixGSCwKICAgICAgICAgICAgICAgICAgYnkueD0iQ291bnRyeSIsYnkueT0iQ291bnRyeSIsIAogICAgICAgICAgICAgICAgYWxsID0gVFJVRSkKCiNDaGVjayB0aGUgbWVyZ2VkIGRhdGEKZGltKG1lcmdlZC5hbGwpCmRpbShtZXJnZWQuYm90aCkKZGltKG1lcmdlZC54KSAjIHNob3VsZCBtYXRjaCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9uIGluIFB1YmxpY09waW5pb24KZGltKG1lcmdlZC55KSAjIHNob3VsZCBtYXRjaCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9uIGluIEZICmBgYAoKIyNEaWFnbm9zdGljCkVhY2ggb2YgdGhlIHR3byBkYXRhIHNldHMgY29udGFpbnMgY291bnRyeSBuYW1lcyB0aGF0IGFyZSBub3QgaW4gdGhlIG90aGVyIGRhdGEgc2V0LiBUaGVyZSBhcmUgdHdvIHBvc3NpYmxlIHJlYXNvbnM6IDEpIHNvbWUgY291bnRyaWVzIGFyZSBtaXNzaW5nIGluIGVpdGhlciBvbmUgb2YgdGhlbTsgMikgc29tZSBjb3VudHJpZXMgYXJlIHNwZWxsZWQgZGlmZmVyZW50bHkgCgpgYGB7cn0Kc2V0ZGlmZihQdWJsaWNPcGluaW9uJENvdW50cnksRkgkQ291bnRyeSkKCiMgQ2hhbmdlIHRob3NlIGNvdW50cnkgbmFtZXMgdGhhdCBhcmUgc3BlbGxlZCBkaWZmZXJlbnRseSAKbGlicmFyeShjYXIpClB1YmxpY09waW5pb24kQ291bnRyeTwtcmVjb2RlKFB1YmxpY09waW5pb24kQ291bnRyeSwiJ0FyZ2VudGknPSdBcmdlbnRpbmEnOydCdXJraUZhc28nPSdCdXJraW5hIEZhc28nOydDaGknPSdDaGluYSc7J0dyZWF0QnJpdGFpbic9J1VuaXRlZCBLaW5nZG9tJzsnTmV3WmVhbGFuZCc9J05ldyBaZWFsYW5kJzsnU291dGhBZnJpY2EnPSdTb3V0aCBBZnJpY2EnOydTb3V0aEtvcmVhJz0nU291dGggS29yZWEnOydUcmluaWRhZGFuZFRvYmFnbyc9J1RyaW5pZGFkIGFuZCBUb2JhZ28nOydVbml0ZWRTdGF0ZXMnPSdVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EnOydWaWV0bSc9J1ZpZXRuYW0nIikKCiNDaGVjayB3aGV0aGVyIHRoZXJlIGFyZSBjb3VudHJpZXMgYXBwZWFyZWQgbW9yZSB0aGFuIG9uY2UKbGVuZ3RoKHVuaXF1ZShQdWJsaWNPcGluaW9uJENvdW50cnkpKQp0YWJsZShQdWJsaWNPcGluaW9uJENvdW50cnkpW3doaWNoKHRhYmxlKFB1YmxpY09waW5pb24kQ291bnRyeSk+MSldIAojRGVsZXRlIHRoZSBleHRyYSBlbnRyeQoKUHVibGljT3BpbmlvbjwtUHVibGljT3Bpbmlvblstd2hpY2goUHVibGljT3BpbmlvbiRDb3VudHJ5PT0iVW5pdGVkIEtpbmdkb20iKVsxXSxdCmBgYAoKIyNNZXJnZSBEYXRhIApgYGB7cn0KbWVyZ2VkIDwtIG1lcmdlKFB1YmxpY09waW5pb24sRkgsYnk9IkNvdW50cnkiLAogICAgICAgICAgICAgICAgYWxsLnggPSBUUlVFKQojQ2hlY2sgd2hldGhlciB5b3UgaGF2ZSBzdWNjZWVkCmRpbShQdWJsaWNPcGluaW9uKQpkaW0obWVyZ2VkKSAgIyBUaGUgbWVyZ2VkIGRhdGEgc2hvdWxkIGhhdmUgdGhlIHNhbWUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBhcyBpbiBQdWJsaWNPcGluaW9uLCBiZWNhdXNlIHdlIHNldCBhbGwueCA9IFRSVUUuIFdlIHNldCB0aGUgbWVyZ2UgZnVuY3Rpb24gdG8gaW5jbHVkZSBhbGwgdGhlIHZhcmlhYmxlIGluIFggZGF0YWZyYW1lLiAKYGBgCgoqKioKSGVscHNoZWV0IG1hZGUgZm9yIFBMU0MgMzA5IGJ5IFlhb3lhbyBEYWkK