This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

** 4.1 Example **

manager <- c(1, 2, 3, 4, 5)
date <- c('10/24/08', '10/28/08', '10/1/08', '10/12/08', '5/1/09')
country <- c('US', 'US', 'UK' , 'UK', 'UK')
gender <-c('M', 'F', 'M', 'M', 'F')
age <- c(32, 45, 25, 39, 99)
q1 <- c(5, 3, 3, 3, 2)
q2 <- c(4, 5, 5, 3, 2)
q3 <- c(5, 2, 5, 4, 1)
q4 <- c(5, 5, 5, NA, 2)
q5 <- c(5, 5, 2, NA, 1)
leadship <- data.frame(
  manager, 
  date,
  country,
  gender,
  age,
  q1, q2, q3, q4, q5, stringsAsFactors = F
)

** 4.2 创建新变量的几种方式 **

*4.2.1

mydata <- data.frame(
  x1 = c(2, 2, 4, 5),
  x2 = c(3, 4, 2, 8)
)
mydata$sumx <- mydata$x1 + mydata$x2
mydata$meanx <- (mydata$x1 + mydata$x2)/2

*4.2.2

attach(mydata)
mydata$sumx = x1 + x2
mydata$meanx = (x1 + x2)/2
detach(mydata)

*4.2.3

mydata <- transform(
  mydata, sumx = x1 + x2,
  meanx = (x1 + x2)/2
)

** 4.3 变量的重编码 **

leadship$age[leadship$age == 99] <- NA
leadship$agecat[leadship$age > 75] <- 'Elder'
leadship$agecat[leadship$age <= 75 & leadship$age >= 55] <- 'Middle aged'
leadship$agecat[leadship$age < 55] <- 'Young'
#或者#

leadship <- within(leadship,{
  age[age == 99] <- NA
  agecat[age > 75] <- 'Elder'
  agecat[age <=75 & age >= 55] <- 'Middle aged'
  agecat[age < 55] <- 'Young'
})
#注意这里使用的是 within,允许修改数据框

若干程序包都提供了实用的变量重编码函数,特别地,car包中的recode()函数可以十分简便地重编码数值型、字符型向量和因子。
而doBy包提供了recodevar()。
R中也有cut(),可将数值型变量按值域分割为多个区间,并返回一个因子。 * recode() in car

library(car)
x <- c(10:100)
recode(x, "lo:20 = 'A'; 20:40 = 'B'; 40:hi = 'C'; else = 'NULL' " )
#lo minimum
#hi maximum

** 4.4 变量的重命名 **
* 交互式
fix()

fix(leadship)
names(leadship)[2] <- 'testDate'
library(plyr)
rename(dataframe, c(oldname = 'newname', oldname = 'newname', ....))
rename(leadship, c(manager = 'managerID', data = 'testDate'))

** 4.5 缺失值 ** 函数is.na()允许检测是否存在缺失值

y <- c(2, 5, 6, NA)
is.na(y)
is.na(leadship[,6:10])

缺失的地方返回值为TRUE。这里的leadership[,6:10]将数据框限定到第6列至第10列。 #需要注意的是,1)缺失值被认为是不可比较的,即便是与缺失值自身的比较,比如,不能使用myvar == NA,这个结果将不会返回TRUE;2)R并不把无限的或者不可能出现的数值标记成缺失值,正无穷和负无穷分别用Inf和-Inf标记,可用is.infinite()判断,不可能的值,如sin(Inf),用NaN符号标记,用is.nan()判断。 #请确保所有的缺失数据在分析之前被妥善地编码为缺失值,否则分析结果将失去意义。 *4.5.1 在分析中排除缺失值 含有缺失值的算术表达式和函数的计算结果也是缺失值。 好多的数值函数都拥有一个na.rm = TRUE的选项,可以在计算之前移除缺失值,并使用剩余值进行计算。

x <- c(1, 2, NA, 3)
y <- sum(x, na.rm = T)
y
[1] 6
y<- sum(x)
y
[1] NA

还可通过函数na.omit()删除所有含有缺失值的观测(行)。

leadship
newdata <- na.omit(leadship)
newdata

** 4.6 日期 ** 日期值通常以字符串的形式输入到R中,然后转化为以数值形式存储的日期变量。 as.Date() as.Date(x, “input_format”) * 日期格式 符号 含义 实例 %d 数字表示的日期(0~31) 01~31 %a 缩写的日期名 Mon %A 非缩写的日期名 Monday %m 月份 (00~12)
%b 缩写的月份 Jan %B 非缩写的月份 January %y 两位数的年份 07 %Y 四位数的年份 2007 日期值的默认输入格式为yyyy-mm-dd

mydates <- as.Date(c('2007-06-22', '2004-02-13'))
mydates
[1] "2007-06-22" "2004-02-13"
strDate <- c("01/05/1965", "08/16/1975")
dates <- as.Date(strDate, "%m/%d/%Y")
dates
[1] "1965-01-05" "1975-08-16"

在leadship数据集中,日期是以mm/dd/yy的格式编码为字符型变量。因此:

myformat <- "%m/%d/%y"
leadship$date <- as.Date(leadship$date, myformat)
leadship$date
[1] "2008-10-24" "2008-10-28" "2008-10-01" "2008-10-12" "2009-05-01"

使用指定格式读取字符型变量,并将其作为一个 日期变量 替换到数据框中。#这种转换一旦完成,就可以使用诸多分析方法对日期进行分析和绘图 * Sys.Date(),返回当天日期
* date(),返回当前日期和时间

Sys.Date()
[1] "2021-04-23"
date()
[1] "Fri Apr 23 15:57:53 2021"
today <- Sys.Date()
format(today, format = "%B %d %Y")
[1] "四月 23 2021"
format(today, format = "%A")
[1] "星期五"
startdate <- as.Date('2001-09-11')
enddate <- as.Date('2021-03-22')
days <- enddate -startdate
days
Time difference of 7132 days
difftime(startdate, enddate, units = 'weeks')
Time difference of -1018.857 weeks
strDates <- as.character(dates)

#要了解字符型数据转换为日期的更多细节,请查看: help(as.Date) help(strftime) help(ISodatatime) library(lubridate) library(timeDate) ** 4.7 类型转换 ** 判断 转换 is.numeric() as.numeric() is.character() as.character() is.vector() as.vector() is.matrix() as.matrix() is.data.frame() as.data.frame() is.factor() as.factor() is.logical() as.logical()

** 4.8 数据排序 ** order(), 默认升序,加-号得到降序的排序结果

newdata <- leadship[order(leadship$age),]
newdata
newdata <- leadship[order(leadship$age),]
newdata
leadship$gender <- factor(leadship$gender, ordered = T, levels = c('M', 'F') )
newdata <- leadship[order(leadship$gender, -age),]
newdata

** 4.9 数据集的合并 ** * 横向合并
merge(),通过一个或多个共有变量进行联结,inner join total <- merge(dataframeA, dataframeB, by = ‘ID’) total <- merge(dataframeA, dateframeB, by = c(‘ID’, ‘country’)) cbind(),直接横向合并,不需要指定一个公共索引。 total <- cbind(A,B), #但A与B必须有相同的函数,且1⃣已经过排序

** 4.10 ** * 选入(保留)变量(列)

newdata <- leadship[,c(6:10)]
newdata
newdata <- leadship[c('q1', 'q2', 'q3', 'q4', 'q5')]
newdata
myvar <- c(paste('q', 1:5, sep = ''))
newdata <- leadship[myvar]
newdata
myvars <- names(leadship) %in% c('q3', 'q4')
myvars
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE
newdata <- leadship[!myvars]
newdata

names(leadship) 生成了一个包含所有变量名的字符型向量 names(leadship) %in% c(‘q3’, ‘q4’) 返回了一个逻辑型向量 !myvars 将逻辑值反转

newdata <- leadship[c(-8, -9)]
newdata <- leadship[1:3, ]
newdata <- leadship[leadship$gender == 'F' & leadship$age > 45,]
leadship$date <- as.Date(leadship$date, "%m/%d/%y")
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2009-10-31")
leadship
newdata <- leadship[leadship$date >= startdate & leadship$date <= enddate, ]
newdata
NA
newdata <- subset(leadship, age >= 35 | age < 24, select = c(q1, q2, q3, q4))
newdata <- subset(leadship, gender = 'M' & age > 25, select = gender:q4)
mysample <- leadship[(sample(1:nrow(leadship), 3, replace = FALSE)),]
mysample
leadship
#第一个参数是一个要从中臭氧的元素组成的向量,
#第二个参数是要抽取的元素数量
#第三个参数表示无放回抽样

#R拥有齐全的抽样工具 library(sampling) library(survey)

** 4.11 使用SQL语句操作数据框 **

#install.packages("sqldf")
#library(sqldf)
newdf <- sqldf("select * from mtcars where carb = 1 order by mpg", row.names = T)
newdf
LS0tCnRpdGxlOiAiUiBpbiBhY3Rpb24gLSBDaGFwdGVyNCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgd29yZF9kb2N1bWVudDogZGVmYXVsdAotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkNtZCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnBsb3QoY2FycykKYGBgCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ21kK09wdGlvbitJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ21kK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuIAoKVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLgoKKiogNC4xIEV4YW1wbGUgKioKYGBge3J9Cm1hbmFnZXIgPC0gYygxLCAyLCAzLCA0LCA1KQpkYXRlIDwtIGMoJzEwLzI0LzA4JywgJzEwLzI4LzA4JywgJzEwLzEvMDgnLCAnMTAvMTIvMDgnLCAnNS8xLzA5JykKY291bnRyeSA8LSBjKCdVUycsICdVUycsICdVSycgLCAnVUsnLCAnVUsnKQpnZW5kZXIgPC1jKCdNJywgJ0YnLCAnTScsICdNJywgJ0YnKQphZ2UgPC0gYygzMiwgNDUsIDI1LCAzOSwgOTkpCnExIDwtIGMoNSwgMywgMywgMywgMikKcTIgPC0gYyg0LCA1LCA1LCAzLCAyKQpxMyA8LSBjKDUsIDIsIDUsIDQsIDEpCnE0IDwtIGMoNSwgNSwgNSwgTkEsIDIpCnE1IDwtIGMoNSwgNSwgMiwgTkEsIDEpCmxlYWRzaGlwIDwtIGRhdGEuZnJhbWUoCiAgbWFuYWdlciwgCiAgZGF0ZSwKICBjb3VudHJ5LAogIGdlbmRlciwKICBhZ2UsCiAgcTEsIHEyLCBxMywgcTQsIHE1LCBzdHJpbmdzQXNGYWN0b3JzID0gRgopCmBgYAoqKiA0LjIg5Yib5bu65paw5Y+Y6YeP55qE5Yeg56eN5pa55byPICoqICAKCio0LjIuMQpgYGB7cn0KbXlkYXRhIDwtIGRhdGEuZnJhbWUoCiAgeDEgPSBjKDIsIDIsIDQsIDUpLAogIHgyID0gYygzLCA0LCAyLCA4KQopCm15ZGF0YSRzdW14IDwtIG15ZGF0YSR4MSArIG15ZGF0YSR4MgpteWRhdGEkbWVhbnggPC0gKG15ZGF0YSR4MSArIG15ZGF0YSR4MikvMgpgYGAKKjQuMi4yCmBgYHtyfQphdHRhY2gobXlkYXRhKQpteWRhdGEkc3VteCA9IHgxICsgeDIKbXlkYXRhJG1lYW54ID0gKHgxICsgeDIpLzIKZGV0YWNoKG15ZGF0YSkKCmBgYAoqNC4yLjMKYGBge3J9Cm15ZGF0YSA8LSB0cmFuc2Zvcm0oCiAgbXlkYXRhLCBzdW14ID0geDEgKyB4MiwKICBtZWFueCA9ICh4MSArIHgyKS8yCikKYGBgCioqIDQuMyDlj5jph4/nmoTph43nvJbnoIEgKiogIAoKKiDpgLvovpHov5DnrpfnrKYgICAKPCwgPD0sID4sID49LCA9PSwgIT0sICF4LCB4fHnvvIh45oiWee+8iSwgeCZ577yIeOWSjHnvvIksIGlzVFJVRSh4Ke+8iOa1i+ivlXjmmK/lkKbkuLpUUlVF77yJICAKKiDov57nu63lnovlj5jph48g6L2s5Li6IOWboOWtkOWeiyAgIAror63lj6V2YXJpYWJsZVtjb25kaXRpb25dIDwtIGV4cHJlc3Npb24sIOS7heWcqGNvbmRpdGlvbuS4ulTnmoTml7blgJnmiafooYzotYvlgLzor63lj6UgIApgYGB7cn0KbGVhZHNoaXAkYWdlW2xlYWRzaGlwJGFnZSA9PSA5OV0gPC0gTkEKbGVhZHNoaXAkYWdlY2F0W2xlYWRzaGlwJGFnZSA+IDc1XSA8LSAnRWxkZXInCmxlYWRzaGlwJGFnZWNhdFtsZWFkc2hpcCRhZ2UgPD0gNzUgJiBsZWFkc2hpcCRhZ2UgPj0gNTVdIDwtICdNaWRkbGUgYWdlZCcKbGVhZHNoaXAkYWdlY2F0W2xlYWRzaGlwJGFnZSA8IDU1XSA8LSAnWW91bmcnCiPmiJbogIUjCgpsZWFkc2hpcCA8LSB3aXRoaW4obGVhZHNoaXAsewogIGFnZVthZ2UgPT0gOTldIDwtIE5BCiAgYWdlY2F0W2FnZSA+IDc1XSA8LSAnRWxkZXInCiAgYWdlY2F0W2FnZSA8PTc1ICYgYWdlID49IDU1XSA8LSAnTWlkZGxlIGFnZWQnCiAgYWdlY2F0W2FnZSA8IDU1XSA8LSAnWW91bmcnCn0pCiPms6jmhI/ov5nph4zkvb/nlKjnmoTmmK8gd2l0aGlu77yM5YWB6K645L+u5pS55pWw5o2u5qGGCmBgYAroi6XlubLnqIvluo/ljIXpg73mj5Dkvpvkuoblrp7nlKjnmoTlj5jph4/ph43nvJbnoIHlh73mlbDvvIznibnliKvlnLDvvIxjYXLljIXkuK3nmoRyZWNvZGUoKeWHveaVsOWPr+S7peWNgeWIhueugOS+v+WcsOmHjee8lueggeaVsOWAvOWei+OAgeWtl+espuWei+WQkemHj+WSjOWboOWtkOOAgiAgCuiAjGRvQnnljIXmj5DkvpvkuoZyZWNvZGV2YXIoKeOAgiAgClLkuK3kuZ/mnIljdXQoKe+8jOWPr+WwhuaVsOWAvOWei+WPmOmHj+aMieWAvOWfn+WIhuWJsuS4uuWkmuS4quWMuumXtO+8jOW5tui/lOWbnuS4gOS4quWboOWtkOOAggoqIHJlY29kZSgpIGluIGNhciAgCmBgYHtyfQpsaWJyYXJ5KGNhcikKeCA8LSBjKDEwOjEwMCkKcmVjb2RlKHgsICJsbzoyMCA9ICdBJzsgMjA6NDAgPSAnQic7IDQwOmhpID0gJ0MnOyBlbHNlID0gJ05VTEwnICIgKQojbG8gbWluaW11bQojaGkgbWF4aW11bQpgYGAKCioqIDQuNCDlj5jph4/nmoTph43lkb3lkI0gKiogIAoqIOS6pOS6kuW8jyAgCmZpeCgpCmBgYHtyfQpmaXgobGVhZHNoaXApCmBgYAoqIOe8lueoi+W8jyAgCm5hbWVzKCkKYGBge3J9Cm5hbWVzKGxlYWRzaGlwKVsyXSA8LSAndGVzdERhdGUnCmBgYAoqIHBseXIg5Ye95pWw5YyF55qEIHJlbmFtZSgpICAKYGBge3J9CmxpYnJhcnkocGx5cikKcmVuYW1lKGRhdGFmcmFtZSwgYyhvbGRuYW1lID0gJ25ld25hbWUnLCBvbGRuYW1lID0gJ25ld25hbWUnLCAuLi4uKSkKcmVuYW1lKGxlYWRzaGlwLCBjKG1hbmFnZXIgPSAnbWFuYWdlcklEJywgZGF0YSA9ICd0ZXN0RGF0ZScpKQpgYGAKCioqIDQuNSDnvLrlpLHlgLwgKioK5Ye95pWwaXMubmEoKeWFgeiuuOajgOa1i+aYr+WQpuWtmOWcqOe8uuWkseWAvApgYGB7cn0KeSA8LSBjKDIsIDUsIDYsIE5BKQppcy5uYSh5KQppcy5uYShsZWFkc2hpcFssNjoxMF0pCmBgYArnvLrlpLHnmoTlnLDmlrnov5Tlm57lgLzkuLpUUlVF44CC6L+Z6YeM55qEbGVhZGVyc2hpcFssNjoxMF3lsIbmlbDmja7moYbpmZDlrprliLDnrKw25YiX6Iez56ysMTDliJfjgIIKI+mcgOimgeazqOaEj+eahOaYr++8jDHvvInnvLrlpLHlgLzooqvorqTkuLrmmK/kuI3lj6/mr5TovoPnmoTvvIzljbPkvr/mmK/kuI7nvLrlpLHlgLzoh6rouqvnmoTmr5TovoPvvIzmr5TlpoLvvIzkuI3og73kvb/nlKhteXZhciA9PSBOQe+8jOi/meS4que7k+aenOWwhuS4jeS8mui/lOWbnlRSVUXvvJsy77yJUuW5tuS4jeaKiuaXoOmZkOeahOaIluiAheS4jeWPr+iDveWHuueOsOeahOaVsOWAvOagh+iusOaIkOe8uuWkseWAvO+8jOato+aXoOept+WSjOi0n+aXoOept+WIhuWIq+eUqEluZuWSjC1JbmbmoIforrDvvIzlj6/nlKhpcy5pbmZpbml0ZSgp5Yik5pat77yM5LiN5Y+v6IO955qE5YC877yM5aaCc2luKEluZiks55SoTmFO56ym5Y+35qCH6K6w77yM55SoaXMubmFuKCnliKTmlq3jgIIKI+ivt+ehruS/neaJgOacieeahOe8uuWkseaVsOaNruWcqOWIhuaekOS5i+WJjeiiq+WmpeWWhOWcsOe8lueggeS4uue8uuWkseWAvO+8jOWQpuWImeWIhuaekOe7k+aenOWwhuWkseWOu+aEj+S5ieOAggoqNC41LjEg5Zyo5YiG5p6Q5Lit5o6S6Zmk57y65aSx5YC8CuWQq+aciee8uuWkseWAvOeahOeul+acr+ihqOi+vuW8j+WSjOWHveaVsOeahOiuoeeul+e7k+aenOS5n+aYr+e8uuWkseWAvOOAggrlpb3lpJrnmoTmlbDlgLzlh73mlbDpg73mi6XmnInkuIDkuKpuYS5ybSA9IFRSVUXnmoTpgInpobnvvIzlj6/ku6XlnKjorqHnrpfkuYvliY3np7vpmaTnvLrlpLHlgLzvvIzlubbkvb/nlKjliankvZnlgLzov5vooYzorqHnrpfjgIIKYGBge3J9CnggPC0gYygxLCAyLCBOQSwgMykKeSA8LSBzdW0oeCwgbmEucm0gPSBUKQp5Cnk8LSBzdW0oeCkKeQpgYGAK6L+Y5Y+v6YCa6L+H5Ye95pWwbmEub21pdCgp5Yig6Zmk5omA5pyJ5ZCr5pyJ57y65aSx5YC855qE6KeC5rWL77yI6KGM77yJ44CCCmBgYHtyfQpsZWFkc2hpcApuZXdkYXRhIDwtIG5hLm9taXQobGVhZHNoaXApCm5ld2RhdGEKYGBgCioqIDQuNiDml6XmnJ8gKioK5pel5pyf5YC86YCa5bi45Lul5a2X56ym5Liy55qE5b2i5byP6L6T5YWl5YiwUuS4re+8jOeEtuWQjui9rOWMluS4uuS7peaVsOWAvOW9ouW8j+WtmOWCqOeahOaXpeacn+WPmOmHj+OAggphcy5EYXRlKCkKYXMuRGF0ZSh4LCAiaW5wdXRfZm9ybWF0IikKKiDml6XmnJ/moLzlvI8K56ym5Y+3ICAgICAgICAgICAgICAgICAg5ZCr5LmJICAgICAgICAgICAgICAgICDlrp7kvosKJWQgICAgICAgICAgICDmlbDlrZfooajnpLrnmoTml6XmnJ/vvIgw772eMzHvvIkgICAgIDAx772eMzEKJWEgICAgICAgICAgICDnvKnlhpnnmoTml6XmnJ/lkI0gICAgICAgICAgICAgICAgICBNb24KJUEgICAgICAgICAgICDpnZ7nvKnlhpnnmoTml6XmnJ/lkI0gICAgICAgICAgICAgICAgTW9uZGF5CiVtICAgICAgICAgICAg5pyI5Lu9ICAgICAgICAgICAgICAgICAgICAgICAg77yIMDDvvZ4xMu+8iSAgCiViICAgICAgICAgICAg57yp5YaZ55qE5pyI5Lu9ICAgICAgICAgICAgICAgICAgICBKYW4KJUIgICAgICAgICAgICDpnZ7nvKnlhpnnmoTmnIjku70gICAgICAgICAgICAgICAgICBKYW51YXJ5CiV5ICAgICAgICAgICAg5Lik5L2N5pWw55qE5bm05Lu9ICAgICAgICAgICAgICAgICAgMDcKJVkgICAgICAgICAgICDlm5vkvY3mlbDnmoTlubTku70gICAgICAgICAgICAgICAgICAyMDA3CuaXpeacn+WAvOeahOm7mOiupOi+k+WFpeagvOW8j+S4unl5eXktbW0tZGQKYGBge3J9Cm15ZGF0ZXMgPC0gYXMuRGF0ZShjKCcyMDA3LTA2LTIyJywgJzIwMDQtMDItMTMnKSkKbXlkYXRlcwpzdHJEYXRlIDwtIGMoIjAxLzA1LzE5NjUiLCAiMDgvMTYvMTk3NSIpCmRhdGVzIDwtIGFzLkRhdGUoc3RyRGF0ZSwgIiVtLyVkLyVZIikKZGF0ZXMKYGBgCuWcqGxlYWRzaGlw5pWw5o2u6ZuG5Lit77yM5pel5pyf5piv5LulbW0vZGQveXnnmoTmoLzlvI/nvJbnoIHkuLrlrZfnrKblnovlj5jph4/jgILlm6DmraTvvJoKYGBge3J9Cm15Zm9ybWF0IDwtICIlbS8lZC8leSIKbGVhZHNoaXAkZGF0ZSA8LSBhcy5EYXRlKGxlYWRzaGlwJGRhdGUsIG15Zm9ybWF0KQpsZWFkc2hpcCRkYXRlCmBgYArkvb/nlKjmjIflrprmoLzlvI/or7vlj5blrZfnrKblnovlj5jph4/vvIzlubblsIblhbbkvZzkuLrkuIDkuKog5pel5pyf5Y+Y6YePIOabv+aNouWIsOaVsOaNruahhuS4reOAgiPov5nnp43ovazmjaLkuIDml6blrozmiJDvvIzlsLHlj6/ku6Xkvb/nlKjor7jlpJrliIbmnpDmlrnms5Xlr7nml6XmnJ/ov5vooYzliIbmnpDlkoznu5jlm74KKiBTeXMuRGF0ZSgp77yM6L+U5Zue5b2T5aSp5pel5pyfICAKKiBkYXRlKCnvvIzov5Tlm57lvZPliY3ml6XmnJ/lkozml7bpl7QgIApgYGB7cn0KU3lzLkRhdGUoKQpkYXRlKCkKYGBgCiogZm90bWF0KHgsIGZvcm1hdCA9ICJvdXRwdXRfZm9ybWF0IinmnaXovpPlh7rmjIflrprmoLzlvI/nmoTml6XmnJ/lgLzvvIzlubbkuJTlj6/ku6Xmj5Dlj5bml6XmnJ/lgLzkuK3nmoTmn5Dkupvpg6jliIbvvJoKYGBge3J9CnRvZGF5IDwtIFN5cy5EYXRlKCkKZm9ybWF0KHRvZGF5LCBmb3JtYXQgPSAiJUIgJWQgJVkiKQoKZm9ybWF0KHRvZGF5LCBmb3JtYXQgPSAiJUEiKQoKYGBgCgoqIOaXpeacn+iuoeeulyAgCmBgYHtyfQpzdGFydGRhdGUgPC0gYXMuRGF0ZSgnMjAwMS0wOS0xMScpCmVuZGRhdGUgPC0gYXMuRGF0ZSgnMjAyMS0wMy0yMicpCmRheXMgPC0gZW5kZGF0ZSAtc3RhcnRkYXRlCmRheXMKCmRpZmZ0aW1lKHN0YXJ0ZGF0ZSwgZW5kZGF0ZSwgdW5pdHMgPSAnd2Vla3MnKSAj6K6h566X5pe26Ze06Ze06ZqUCmBgYAoKKiDml6XmnJ/lj5jph4/ovazmjaLkuLrlrZfnrKblnovlj5jph48KYXMuY2hhcmFjdGVyKGRhdGVzKQpgYGB7cn0Kc3RyRGF0ZXMgPC0gYXMuY2hhcmFjdGVyKGRhdGVzKQoKYGBgCiPopoHkuobop6PlrZfnrKblnovmlbDmja7ovazmjaLkuLrml6XmnJ/nmoTmm7TlpJrnu4boioLvvIzor7fmn6XnnIs6CmhlbHAoYXMuRGF0ZSkKaGVscChzdHJmdGltZSkKaGVscChJU29kYXRhdGltZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkodGltZURhdGUpCioqIDQuNyDnsbvlnovovazmjaIgKioK5Yik5patICAgICAgICAgICAgICAgIOi9rOaNogppcy5udW1lcmljKCkgICAgICAgIGFzLm51bWVyaWMoKQppcy5jaGFyYWN0ZXIoKSAgICAgIGFzLmNoYXJhY3RlcigpCmlzLnZlY3RvcigpICAgICAgICAgYXMudmVjdG9yKCkKaXMubWF0cml4KCkgICAgICAgICBhcy5tYXRyaXgoKQppcy5kYXRhLmZyYW1lKCkgICAgIGFzLmRhdGEuZnJhbWUoKQppcy5mYWN0b3IoKSAgICAgICAgIGFzLmZhY3RvcigpCmlzLmxvZ2ljYWwoKSAgICAgICAgYXMubG9naWNhbCgpCgoqKiA0Ljgg5pWw5o2u5o6S5bqPICoqCm9yZGVyKCksIOm7mOiupOWNh+W6j++8jOWKoC3lj7flvpfliLDpmY3luo/nmoTmjpLluo/nu5PmnpwKYGBge3J9Cm5ld2RhdGEgPC0gbGVhZHNoaXBbb3JkZXIobGVhZHNoaXAkYWdlKSxdCm5ld2RhdGEKbmV3ZGF0YSA8LSBsZWFkc2hpcFtvcmRlcihsZWFkc2hpcCRhZ2UpLF0KbmV3ZGF0YQpsZWFkc2hpcCRnZW5kZXIgPC0gZmFjdG9yKGxlYWRzaGlwJGdlbmRlciwgb3JkZXJlZCA9IFQsIGxldmVscyA9IGMoJ00nLCAnRicpICkKbmV3ZGF0YSA8LSBsZWFkc2hpcFtvcmRlcihsZWFkc2hpcCRnZW5kZXIsIC1hZ2UpLF0gI+WFiOaAp+WIq++8jOWQjuW5tOm+hApuZXdkYXRhCmBgYAoqKiA0Ljkg5pWw5o2u6ZuG55qE5ZCI5bm2ICoqCiog5qiq5ZCR5ZCI5bm2ICAKbWVyZ2UoKe+8jOmAmui/h+S4gOS4quaIluWkmuS4quWFseacieWPmOmHj+i/m+ihjOiBlOe7k++8jGlubmVyIGpvaW4KdG90YWwgPC0gbWVyZ2UoZGF0YWZyYW1lQSwgZGF0YWZyYW1lQiwgYnkgPSAnSUQnKQp0b3RhbCA8LSBtZXJnZShkYXRhZnJhbWVBLCBkYXRlZnJhbWVCLCBieSA9IGMoJ0lEJywgJ2NvdW50cnknKSkKY2JpbmQoKe+8jOebtOaOpeaoquWQkeWQiOW5tu+8jOS4jemcgOimgeaMh+WumuS4gOS4quWFrOWFsee0ouW8leOAggp0b3RhbCA8LSBjYmluZChBLEIpLCAj5L2GQeS4jkLlv4XpobvmnInnm7jlkIznmoTlh73mlbDvvIzkuJQx4oOj5bey57uP6L+H5o6S5bqPCgoqIOe6teWQkeWQiOW5tiAgCnJiaW5kKCksIEHlkoxC5b+F6aG75pyJ55u45ZCM55qE5Y+Y6YeP77yM6aG65bqP5Y+v5Lul5LiN5b+F55u45ZCMCnRvdGFsIDwtIHJiaW5kKEEsIEIpCuWmguaenEHkuI5C5Lit5Y+Y6YeP5LiN5ZCM77yaMe+8ieWIoOmZpOWkmuS9meeahOWPmOmHj++8mzLvvInlop7liqBOQee8uuWkseingua1iwoKKiogNC4xMCAqKgoqIOmAieWFpe+8iOS/neeVme+8ieWPmOmHj++8iOWIl++8iQpgYGB7cn0KbmV3ZGF0YSA8LSBsZWFkc2hpcFssYyg2OjEwKV0KbmV3ZGF0YQpuZXdkYXRhIDwtIGxlYWRzaGlwW2MoJ3ExJywgJ3EyJywgJ3EzJywgJ3E0JywgJ3E1JyldCm5ld2RhdGEKbXl2YXIgPC0gYyhwYXN0ZSgncScsIDE6NSwgc2VwID0gJycpKQpuZXdkYXRhIDwtIGxlYWRzaGlwW215dmFyXQpuZXdkYXRhCmBgYAoqIOWJlOmZpOWPmOmHj++8iOWIl++8iSAgICAKYGBge3J9Cm15dmFycyA8LSBuYW1lcyhsZWFkc2hpcCkgJWluJSBjKCdxMycsICdxNCcpCm15dmFycwpuZXdkYXRhIDwtIGxlYWRzaGlwWyFteXZhcnNdCm5ld2RhdGEKYGBgCm5hbWVzKGxlYWRzaGlwKSDnlJ/miJDkuobkuIDkuKrljIXlkKvmiYDmnInlj5jph4/lkI3nmoTlrZfnrKblnovlkJHph48KbmFtZXMobGVhZHNoaXApICVpbiUgYygncTMnLCAncTQnKSDov5Tlm57kuobkuIDkuKrpgLvovpHlnovlkJHph48KIW15dmFycyDlsIbpgLvovpHlgLzlj43ovawKYGBge3J9Cm5ld2RhdGEgPC0gbGVhZHNoaXBbYygtOCwgLTkpXQoj55u05o6l5Yig6Zmk56ysOOWSjDnliJcKbGVhZHNoaXAkcTMgPC0gbGVhZHNoaXAkcTQgPC0gTlVMTAoj6K6+572u5Li6IOacquWumuS5ie+8jCDkuI3lkIzkuo5OQQpgYGAKKiDpgInlhaXop4LmtYvvvIjooYzvvIkgIApgYGB7cn0KbmV3ZGF0YSA8LSBsZWFkc2hpcFsxOjMsIF0KbmV3ZGF0YSA8LSBsZWFkc2hpcFtsZWFkc2hpcCRnZW5kZXIgPT0gJ0YnICYgbGVhZHNoaXAkYWdlID4gNDUsXQpsZWFkc2hpcCRkYXRlIDwtIGFzLkRhdGUobGVhZHNoaXAkZGF0ZSwgIiVtLyVkLyV5IikKc3RhcnRkYXRlIDwtIGFzLkRhdGUoIjIwMDktMDEtMDEiKQplbmRkYXRlIDwtIGFzLkRhdGUoIjIwMDktMTAtMzEiKQpsZWFkc2hpcApuZXdkYXRhIDwtIGxlYWRzaGlwW2xlYWRzaGlwJGRhdGUgPj0gc3RhcnRkYXRlICYgbGVhZHNoaXAkZGF0ZSA8PSBlbmRkYXRlLCBdCm5ld2RhdGEKCmBgYAoqIOS9v+eUqHN1YnNldCgp5Ye95pWwCuS9v+eUqHN1YnNldCgp5Ye95pWw5aSn5qaC5piv6YCJ5oup5Y+Y6YeP5ZKM6KeC5rWL5pyA566A5Y2V55qE5pa55rOV5LqG44CCCmBgYHtyfQpuZXdkYXRhIDwtIHN1YnNldChsZWFkc2hpcCwgYWdlID49IDM1IHwgYWdlIDwgMjQsIHNlbGVjdCA9IGMocTEsIHEyLCBxMywgcTQpKQpuZXdkYXRhIDwtIHN1YnNldChsZWFkc2hpcCwgZ2VuZGVyID0gJ00nICYgYWdlID4gMjUsIHNlbGVjdCA9IGdlbmRlcjpxNCkgI+mAieaLqeaJgOaciTI15bKB5Lul5LiK55qE55S35oCn77yM5bm25L+d55WZ5Y+Y6YePZ2VuZGVy5YiwcTQKYGBgCgoqIOS9v+eUqHNhbXBsZSgp5Ye95pWw77yM5pyJ5pS+5Zue77yI5oiW5LiN5pS+5Zue77yJ5oq95Y+W5aSn5bCP5Li6bueahOagt+acrOOAggpgYGB7cn0KbXlzYW1wbGUgPC0gbGVhZHNoaXBbKHNhbXBsZSgxOm5yb3cobGVhZHNoaXApLCAzLCByZXBsYWNlID0gRkFMU0UpKSxdICMjI++8ge+8ge+8geazqOaEj+aMieihjOS/neeVmeaVsOaNrueahOaXtuWAme+8jOS4jeimgeW/mOS6hiAsIApteXNhbXBsZQoj56ys5LiA5Liq5Y+C5pWw5piv5LiA5Liq6KaB5LuO5Lit5oq95qC355qE5YWD57Sg57uE5oiQ55qE5ZCR6YeP77yMCiPnrKzkuozkuKrlj4LmlbDmmK/opoHmir3lj5bnmoTlhYPntKDmlbDph48KI+esrOS4ieS4quWPguaVsOihqOekuuaXoOaUvuWbnuaKveagtwpgYGAKI1Lmi6XmnInpvZDlhajnmoTmir3moLflt6XlhbcKbGlicmFyeShzYW1wbGluZykKbGlicmFyeShzdXJ2ZXkpCgoqKiA0LjExIOS9v+eUqFNRTOivreWPpeaTjeS9nOaVsOaNruahhiAqKgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoInNxbGRmIikKI2xpYnJhcnkoc3FsZGYpCm5ld2RmIDwtIHNxbGRmKCJzZWxlY3QgKiBmcm9tIG10Y2FycyB3aGVyZSBjYXJiID0gMSBvcmRlciBieSBtcGciLCByb3cubmFtZXMgPSBUKQpuZXdkZgpgYGAKCgoKCgo=