UI 交互

  • View(data), 显示表格化的数据
  • fix(data), 显示表格化的数据,且可以编辑数值

bruceR::import()/export()

一站式导入 / 导出任意存储格式的数据表

  • 主要参数

    • file:带后缀的文件名(包括但不限于 TXT、CSV、Excel、SPSS、Stata 等),如果不设定,则从剪贴板导入 / 导出至剪贴板
    • sheet:如果是 Excel 文件,可以额外指定是哪个 Sheet 表单(默认是第一个 Sheet)
    • range:如果是 Excel 文件,可以额外指定数据的单元格范围(默认是全部单元格)
    • encoding:字符编码("UTF-8""GBK""CP936" 中的一种),一般用于会出现乱码的使用 UTF-8 编码的带有中文字符的 CSV 文件(设为 "UTF-8" 即可)
    • header:导入时是否把第一行作为变量名(导出时是否包含变量名)?默认是 TRUE,可设为 FALSE
    • as:导入后使用哪种数据框类型?默认是 "data.frame"可设为 "data.table""tibble"
  • 使用示例

# import() 支持导入 txt、csv、xlsx、rda、rds等
data <- import("MyData.csv")
data <- import("MyData.xlsx")
data <- import("MyData.sav")
data <- import(file = "aaa.csv", as = "data.table")

# 导出
export(data, file = "NewData.csv")
export(data, file = "NewData.xlsx")
export(data, file = "NewData.sav")

# 一次同时导出两个数据集到Excel
export(list(airquality, npk), sheet = c("air", "npk"), file = "Two_Datasets.xlsx")

Input

import data as tidy-style cheatsheet.pdf,内含三个包: readr, readxl, googlesheets4

from Console

<-c()

直接输入一个向量

y <- c("a", "b", "c")
y
#> [1] "a" "b" "c"

scan() 控制台输入一个向量

单次回车或空格间隔元素,以两次回车结束输入。

x <- scan()

from Package

  • 查看所有预先提供的数据集 data()
  • 查看某个包所有预先提供的数据集 data(package=" ")
  • 读入某个包的数据 data(dataname, package=" ")
library(SemiPar)
data(package = "SemiPar")
data(copper, package = "SemiPar")
head(copper)
#>   sample.num    id zone xcoord ycoord zcoord grade core.length
#> 1          1 BHL01    1    220    625    122  1.34           5
#> 2          2 BHL01    1    220    625    117  0.98           5
#> 3          3 BHL01    1    220    625    112  1.29           5
#> 4          4 BHL01    1    220    625    107  1.18           5
#> 5          5 BHL01    1    220    625    102  1.10           5
#> 6          6 BHL01    1    220    625     97  0.46           5

from TXT

readr::read_lines() 将文本文件的各行读为字符串向量的各元素

readr::read_table() 读空格分割的文件

from JSON

jsonlite::fromJSON(path)

from 二进制文件

.rda

load('xxx.rda')

.RDS

readRDS()

from CSV

data.table::fread()

对 csv 文件优先使用,读为 data.table

注意两点:

  1. 一个是不要将 csv 中的数值型字符串读为 integer 等数值型变量(如将 “004” 读为 4),用 colClasses= 规定
  2. 注意文件编码
ISO3166 <- fread("./data/ISO-3166.csv", colClasses = list(character = c(4, 9, 10, 11)), encoding = "UTF-8")
str(ISO3166)
#> Classes 'data.table' and 'data.frame':   249 obs. of  11 variables:
#>  $ name                    : chr  "Afghanistan" "Åland Islands" "Albania" "Algeria" ...
#>  $ alpha-2                 : chr  "AF" "AX" "AL" "DZ" ...
#>  $ alpha-3                 : chr  "AFG" "ALA" "ALB" "DZA" ...
#>  $ country-code            : chr  "004" "248" "008" "012" ...
#>  $ iso_3166-2              : chr  "ISO 3166-2:AF" "ISO 3166-2:AX" "ISO 3166-2:AL" "ISO 3166-2:DZ" ...
#>  $ region                  : chr  "Asia" "Europe" "Europe" "Africa" ...
#>  $ sub-region              : chr  "Southern Asia" "Northern Europe" "Southern Europe" "Northern Africa" ...
#>  $ intermediate-region     : chr  "" "" "" "" ...
#>  $ region-code             : chr  "142" "150" "150" "002" ...
#>  $ sub-region-code         : chr  "034" "154" "039" "015" ...
#>  $ intermediate-region-code: chr  "" "" "" "" ...
#>  - attr(*, ".internal.selfref")=<externalptr>
ISO3166 <- fread("./data/ISO-3166.csv", select = list(character = c(1, 3, 4)), encoding = "UTF-8")
str(ISO3166)
#> Classes 'data.table' and 'data.frame':   249 obs. of  3 variables:
#>  $ name        : chr  "Afghanistan" "Åland Islands" "Albania" "Algeria" ...
#>  $ alpha-3     : chr  "AFG" "ALA" "ALB" "DZA" ...
#>  $ country-code: chr  "004" "248" "008" "012" ...
#>  - attr(*, ".internal.selfref")=<externalptr>

readr::read_csv()

  • read_csv()将文件读为tibble
  • 不指定列的数据类型时,read_csv()会打印一份数据列说明,给出每个列的名称和它自动解析的列的类型。这是readr包的一项重要功能。但强烈建议编程者提供col_types参数
  • 首行:
    • col_names = T, 不使用首行作为列名称
    • col_names = F, 不使用首行作为列名,函数自动将列标记为X1, X2, …
    • col_names = 字符串向量,直接赋列名称
  • skip = n, 忽略前n行(通常为MetaData)
  • comment = '#', 忽略所有以#开头的行
  • na =, 设定缺失值,默认各种 white space1NA都是缺失值

parse_*()

readr 解析文本文件的原理

解析依靠函数族parse_*()。这些函数接受一个字符向量,并返回一个特定向量,如逻辑、整数或日期向量。具体来说,重要的解析函数有 8 种。

  • parse_logical()和parse_integer()分别解析逻辑值和整数。这两个解析函数基本不会出现问题
  • parse_double()是严格的数值型解析函数,parse_number()则是灵活的数值型解析函数。这两个函数要比你预想的更复杂,因为世界各地书写数值的方式不尽相同
  • parse_character()似乎太过简单,甚至没必要存在。但一个棘手的问题使得这个函数变得非常重要:字符编码
  • parse_factor()函数可以创建因子,R使用这种数据结构来表示分类变量
  • parse_datetime()、parse_date()和parse_time()函数可以解析不同类型的日期和时间。它们是最复杂的,因为有太多不同的日期书写形式

所以读取 csv 远比你想象的复杂,自己造轮子会累死。

解析数值

  1. parse_double()locale(decimal_mark=)参数定义当地的小数点书写形式。
parse_double("3121,23", locale = locale(decimal_mark = ","))
#> [1] 3121.23
  1. parse_number()可以忽略数值前后的非数值型字符。这个函数特别适合处理货币和百分比,也可以提取嵌在文本中的数值。
parse_number("It cost $123.45.")
#> [1] 123.45
parse_number("I want 45% of it.")
#> [1] 45
  1. parse_number()locale(grouping_mark=)参数可以忽略位数间隔符(grouping mark)
parse_number("123.456.789", locale = locale(grouping_mark = "."))
#> [1] 123456789

解析字符串

非英文字符的编码方式有许多种,对其解码需要用locale(encoding=)参数设置编码方式,

x2 <- "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"
parse_character(x2, locale = locale(encoding = "Shift-JIS"))
#> [1] "こんにちは"

解析因子

fruit <- c("apple", "banana")
parse_factor(c("apple", "banana", "bananana"), levels = fruit)
#> Warning: 1 parsing failure.
#> row col           expected   actual
#>   3  -- value in level set bananana
#> [1] apple  banana <NA>  
#> attr(,"problems")
#> # A tibble: 1 × 4
#>     row   col expected           actual  
#>   <int> <int> <chr>              <chr>   
#> 1     3    NA value in level set bananana
#> Levels: apple banana

解析日期与时间

  • parse_datetime() 接受符合 ISO 8601 标准的日期时间。
parse_datetime("2010-10-01T2010")
#> [1] "2010-10-01 20:10:00 UTC"
# 如果时间被省略了,那么它就会被设置为午夜0点0分
parse_datetime("20101010")
#> [1] "2010-10-10 UTC"
  • parse_date() 接受是四位数的年份+-/+月+-/+日
parse_date("2010-10-01")
#> [1] "2010-10-01"
  • parse_time() 接受小时+:+分钟+[:+秒]+[am/pm]
library(hms)
parse_time("01:10 am")
#> 01:10:00
parse_time("20:10:01")
#> 20:10:01
  • 自己设定时间格式
符号 含义
%Y 4位数年份
%y 2位数年份(00-69 → 2000-2069, 70-99 → 1970-1999)
%m 2位数月份
%b 简写月份
%B 月份全称
%d 日期,一位数或两位数
%e 两位数日期
%H 0-23小时
%I%p 0-12小时,%p表示am/pm
%M 分钟
%S 整数秒
%OS 实数秒
%Z 时区
%z 与国际标准时间的时差
%. 忽略一个非数值字符
%* 忽略所有非数值字符

注意,若对非英语月份名称使用 %b 或 %B,需要在locale()函数中设置语言参数。

parse_date("1 janvier 2015", "%d %B %Y", locale = locale("fr"))
#> [1] "2015-01-01"

Output

to Console

cat(... , file = "", sep = " ", fill = FALSE, labels = NULL, append = FALSE)

file:一个文件链接或者文件名,如果不写此参数,表示输出到控制台

sep:分隔符

append:是否追加,当且仅当参数file是文件名而非链接时,此参数才有效。

注意:cat()默认用空格分开各部分,不会以换行作为输出的结尾

print()

区别:print() 输出字符串向量,cat() 输出字符串的内容,就像显示在网页或打印结果上

r$> cat("Hello")
Hello
r$> print('Hello')
[1] "Hello"

to TXT

readr::write_lines()

sink("filename", append=TRUE, split=TRUE) 文本输出,是否追加,是否同时输出在屏幕上

sink() 取消文本输出到文件

to JSON

  1. jsonlite::toJSON()保存为 JSON 字符串
  2. readr::write_lines(data, path) 保存为 json 文件
dir.create("./data")
#> Warning in dir.create("./data"): '.\data' already exists
iris %>%
  head() %>%
  jsonlite::toJSON() %>%
  readr::write_lines("./data/iris.json")

to .rda

save(obj, file = 'xxx.rda') 保存一些变量。第一个参数省略时保存所有对象。

save.image('xxx.rda') 保存整个工作空间中的所有变量。对于长期连续编程,这非常有用。

to .RDS

saveRDS() 保存单个对象到一个RDS文件

to CSV

data.table::fwirte()

readr::write_csv()

这个函数输出的文件能够顺利读取的概率更高,因为:

  • 它们总是使用UTF-8 对字符串进行编码
  • 它们使用ISO 8601格式来保存日期和日期时间数据,以便这些数据不论在何种环境下都更容易解析

注意,当保存为CSV文件时,列的数据类型信息就丢失了:这使得CSV文件在暂存临时结果时有些不可靠——每次加载时都要重建列类型。


  1. \n\t等特殊字符。↩︎

LS0tDQp0aXRsZTogIklP5Y+K6Kej5p6Q5paH5pysIg0Kc3VidGl0bGU6ICcnDQphdXRob3I6ICJIdW1vb24iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IGh0bWxfZG9jdW1lbnQNCmRvY3VtZW50Y2xhc3M6IGN0ZXhhcnQNCmNsYXNzb3B0aW9uOiBoeXBlcnJlZiwNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kc291cmNlKCIuLi9SbWFya2Rvd24tdGVtcGxhdGUvUm1hcmtkb3duX2NvbmZpZy5SIikNCg0KIyMgZ2xvYmFsIG9wdGlvbnMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgd2lkdGggPSBjb25maWckd2lkdGgsDQogIGZpZy53aWR0aCA9IGNvbmZpZyRmaWcud2lkdGgsDQogIGZpZy5hc3AgPSBjb25maWckZmlnLmFzcCwNCiAgb3V0LndpZHRoID0gY29uZmlnJG91dC53aWR0aCwNCiAgZmlnLmFsaWduID0gY29uZmlnJGZpZy5hbGlnbiwNCiAgZmlnLnBhdGggPSBjb25maWckZmlnLnBhdGgsDQogIGZpZy5zaG93ID0gY29uZmlnJGZpZy5zaG93LA0KICB3YXJuID0gY29uZmlnJHdhcm4sDQogIHdhcm5pbmcgPSBjb25maWckd2FybmluZywNCiAgbWVzc2FnZSA9IGNvbmZpZyRtZXNzYWdlLA0KICBlY2hvID0gY29uZmlnJGVjaG8sDQogIGV2YWwgPSBjb25maWckZXZhbCwNCiAgdGlkeSA9IGNvbmZpZyR0aWR5LA0KICBjb21tZW50ID0gY29uZmlnJGNvbW1lbnQsDQogIGNvbGxhcHNlID0gY29uZmlnJGNvbGxhcHNlLA0KICBjYWNoZSA9IGNvbmZpZyRjYWNoZSwNCiAgY2FjaGUuY29tbWVudHMgPSBjb25maWckY2FjaGUuY29tbWVudHMsDQogIGF1dG9kZXAgPSBjb25maWckYXV0b2RlcA0KKQ0KDQoNCiMjIHVzZSBuZWNlc3NhcnkgcGFja2FnZXMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkobWFncml0dHIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoaHRtbHdpZGdldHMpDQpgYGANCg0KIyMgVUkg5Lqk5LqSDQoNCi0gYFZpZXcoZGF0YSlgLCDmmL7npLrooajmoLzljJbnmoTmlbDmja4NCi0gYGZpeChkYXRhKWAsIOaYvuekuuihqOagvOWMlueahOaVsOaNru+8jOS4lOWPr+S7pee8lui+keaVsOWAvA0KDQojIyBgYnJ1Y2VSOjppbXBvcnQoKS9leHBvcnQoKWANCg0K5LiA56uZ5byP5a+85YWlIC8g5a+85Ye65Lu75oSP5a2Y5YKo5qC85byP55qE5pWw5o2u6KGoDQoNCi0g5Li76KaB5Y+C5pWwDQoNCiAgLSBgZmlsZWDvvJrluKblkI7nvIDnmoTmlofku7blkI3vvIjljIXmi6zkvYbkuI3pmZDkuo4gVFhU44CBQ1NW44CBRXhjZWzjgIFTUFNT44CBU3RhdGEg562J77yJ77yM5aaC5p6c5LiN6K6+5a6a77yM5YiZ5LuO5Ymq6LS05p2/5a+85YWlIC8g5a+85Ye66Iez5Ymq6LS05p2/DQogIC0gYHNoZWV0YO+8muWmguaenOaYryBFeGNlbCDmlofku7bvvIzlj6/ku6Xpop3lpJbmjIflrprmmK/lk6rkuKogU2hlZXQg6KGo5Y2V77yI6buY6K6k5piv56ys5LiA5LiqIFNoZWV077yJDQogIC0gYHJhbmdlYO+8muWmguaenOaYryBFeGNlbCDmlofku7bvvIzlj6/ku6Xpop3lpJbmjIflrprmlbDmja7nmoTljZXlhYPmoLzojIPlm7TvvIjpu5jorqTmmK/lhajpg6jljZXlhYPmoLzvvIkNCiAgLSBgZW5jb2Rpbmdg77ya5a2X56ym57yW56CB77yIYCJVVEYtOCJg44CBYCJHQksiYOOAgWAiQ1A5MzYiYCDkuK3nmoTkuIDnp43vvInvvIzkuIDoiKznlKjkuo7kvJrlh7rnjrDkubHnoIHnmoTkvb/nlKggVVRGLTgg57yW56CB55qE5bim5pyJ5Lit5paH5a2X56ym55qEIENTViDmlofku7bvvIjorr7kuLogYCJVVEYtOCJgIOWNs+WPr++8iQ0KICAtIGBoZWFkZXJg77ya5a+85YWl5pe25piv5ZCm5oqK56ys5LiA6KGM5L2c5Li65Y+Y6YeP5ZCN77yI5a+85Ye65pe25piv5ZCm5YyF5ZCr5Y+Y6YeP5ZCN77yJ77yf6buY6K6k5pivIGBUUlVFYO+8jOWPr+iuvuS4uiBgRkFMU0VgDQogIC0gYGFzYO+8muWvvOWFpeWQjuS9v+eUqOWTquenjeaVsOaNruahhuexu+Wei++8n+m7mOiupOaYryBgImRhdGEuZnJhbWUiYO+8jCoq5Y+v6K6+5Li6IGAiZGF0YS50YWJsZSJgKiog5oiWIGAidGliYmxlImANCg0KLSDkvb/nlKjnpLrkvosNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIGltcG9ydCgpIOaUr+aMgeWvvOWFpSB0eHTjgIFjc3bjgIF4bHN444CBcmRh44CBcmRz562JDQpkYXRhIDwtIGltcG9ydCgiTXlEYXRhLmNzdiIpDQpkYXRhIDwtIGltcG9ydCgiTXlEYXRhLnhsc3giKQ0KZGF0YSA8LSBpbXBvcnQoIk15RGF0YS5zYXYiKQ0KZGF0YSA8LSBpbXBvcnQoZmlsZSA9ICJhYWEuY3N2IiwgYXMgPSAiZGF0YS50YWJsZSIpDQoNCiMg5a+85Ye6DQpleHBvcnQoZGF0YSwgZmlsZSA9ICJOZXdEYXRhLmNzdiIpDQpleHBvcnQoZGF0YSwgZmlsZSA9ICJOZXdEYXRhLnhsc3giKQ0KZXhwb3J0KGRhdGEsIGZpbGUgPSAiTmV3RGF0YS5zYXYiKQ0KDQojIOS4gOasoeWQjOaXtuWvvOWHuuS4pOS4quaVsOaNrumbhuWIsEV4Y2VsDQpleHBvcnQobGlzdChhaXJxdWFsaXR5LCBucGspLCBzaGVldCA9IGMoImFpciIsICJucGsiKSwgZmlsZSA9ICJUd29fRGF0YXNldHMueGxzeCIpDQpgYGANCg0KIyMgSW5wdXQNCg0KPGEgaHJlZj0iLi4vcGRmL2NoZWF0c2hlZXQtZGF0YS1pbXBvcnQucGRmIj48c3Ryb25nPmltcG9ydCBkYXRhIGFzICB0aWR5LXN0eWxlIGNoZWF0c2hlZXQucGRmPC9zdHJvbmc+PC9hPu+8jOWGheWQq+S4ieS4quWMhTogcmVhZHIsIHJlYWR4bCwgZ29vZ2xlc2hlZXRzNA0KDQo8b2JqZWN0IGRhdGE9Ii4uL3BkZi9jaGVhdHNoZWV0LWRhdGEtaW1wb3J0LnBkZiIgdHlwZT0iYXBwbGljYXRpb24vcGRmIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIj48L29iamVjdD4NCg0KDQojIyMgZnJvbSBDb25zb2xlDQoNCiMjIyMgYDwtYygpYA0KDQrnm7TmjqXovpPlhaXkuIDkuKrlkJHph48NCg0KYGBge3J9DQp5IDwtIGMoImEiLCAiYiIsICJjIikNCnkNCmBgYA0KDQojIyMjIGBzY2FuKClgIOaOp+WItuWPsOi+k+WFpeS4gOS4quWQkemHjw0KDQrku6UqKuWNleasoeWbnui9puaIluepuuagvCoq6Ze06ZqU5YWD57Sg77yM5Lul5Lik5qyh5Zue6L2m57uT5p2f6L6T5YWl44CCDQpgYGB7ciwgZXZhbD1GQUxTRX0NCnggPC0gc2NhbigpDQpgYGANCg0KIyMjIGZyb20gUGFja2FnZQ0KDQoqIOafpeeci+aJgOaciemihOWFiOaPkOS+m+eahOaVsOaNrumbhiBgZGF0YSgpYA0KKiDmn6XnnIvmn5DkuKrljIXmiYDmnInpooTlhYjmj5DkvpvnmoTmlbDmja7pm4YgYGRhdGEocGFja2FnZT0iICIpYA0KKiDor7vlhaXmn5DkuKrljIXnmoTmlbDmja4gYGRhdGEoZGF0YW5hbWUsIHBhY2thZ2U9IiAiKWANCg0KYGBge3J9DQpsaWJyYXJ5KFNlbWlQYXIpDQpkYXRhKHBhY2thZ2UgPSAiU2VtaVBhciIpDQpkYXRhKGNvcHBlciwgcGFja2FnZSA9ICJTZW1pUGFyIikNCmhlYWQoY29wcGVyKQ0KYGBgDQoNCiMjIyBmcm9tIFRYVA0KDQpgcmVhZHI6OnJlYWRfbGluZXMoKWAg5bCG5paH5pys5paH5Lu255qE5ZCE6KGM6K+75Li65a2X56ym5Liy5ZCR6YeP55qE5ZCE5YWD57SgDQoNCmByZWFkcjo6cmVhZF90YWJsZSgpYCDor7vnqbrmoLzliIblibLnmoTmlofku7YNCg0KIyMjIGZyb20gSlNPTg0KDQpganNvbmxpdGU6OmZyb21KU09OKHBhdGgpYA0KDQojIyMgZnJvbSDkuozov5vliLbmlofku7YNCg0KIyMjIyAucmRhDQoNCmBsb2FkKCd4eHgucmRhJylgDQoNCiMjIyMgLlJEUw0KDQpgcmVhZFJEUygpYA0KDQojIyMgZnJvbSBDU1YNCg0KIyMjIyBgZGF0YS50YWJsZTo6ZnJlYWQoKWANCg0KKio8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+5a+5IGNzdiDmlofku7bkvJjlhYjkvb/nlKjvvIzor7vkuLogZGF0YS50YWJsZTwvc3Bhbj4qKg0KDQrms6jmhI/kuKTngrnvvJoNCg0KMS4g5LiA5Liq5pivPHNwYW4gc3R5bGU9ImNvbG9yOnJlZDsiPuS4jeimgeWwhiBjc3Yg5Lit55qE5pWw5YC85Z6L5a2X56ym5Liy6K+75Li6IGludGVnZXIg562J5pWw5YC85Z6L5Y+Y6YePPC9zcGFuPu+8iOWmguWwhiAiMDA0IiDor7vkuLogNO+8ie+8jOeUqCBgY29sQ2xhc3Nlcz1gIOinhOWumg0KMi4g5rOo5oSP5paH5Lu257yW56CBDQoNCmBgYHtyfQ0KSVNPMzE2NiA8LSBmcmVhZCgiLi9kYXRhL0lTTy0zMTY2LmNzdiIsIGNvbENsYXNzZXMgPSBsaXN0KGNoYXJhY3RlciA9IGMoNCwgOSwgMTAsIDExKSksIGVuY29kaW5nID0gIlVURi04IikNCnN0cihJU08zMTY2KQ0KYGBgDQoNCmBgYHtyfQ0KSVNPMzE2NiA8LSBmcmVhZCgiLi9kYXRhL0lTTy0zMTY2LmNzdiIsIHNlbGVjdCA9IGxpc3QoY2hhcmFjdGVyID0gYygxLCAzLCA0KSksIGVuY29kaW5nID0gIlVURi04IikNCnN0cihJU08zMTY2KQ0KYGBgDQoNCiMjIyMgYHJlYWRyOjpyZWFkX2NzdigpYA0KDQotIGByZWFkX2NzdigpYOWwhuaWh+S7tuivu+S4unRpYmJsZSAgICANCi0g5LiN5oyH5a6a5YiX55qE5pWw5o2u57G75Z6L5pe277yMYHJlYWRfY3N2KClg5Lya5omT5Y2w5LiA5Lu95pWw5o2u5YiX6K+05piO77yM57uZ5Ye65q+P5Liq5YiX55qE5ZCN56ew5ZKM5a6DKiroh6rliqjop6PmnpDnmoTliJfnmoTnsbvlnosqKuOAgui/meaYr3JlYWRy5YyF55qE5LiA6aG56YeN6KaB5Yqf6IO944CC5L2G5by654OI5bu66K6u57yW56iL6ICF5o+Q5L6bYGNvbF90eXBlc2Dlj4LmlbANCi0g6aaW6KGM77yaDQogIC0gYGNvbF9uYW1lcyA9IFRgLCDkuI3kvb/nlKjpppbooYzkvZzkuLrliJflkI3np7ANCiAgLSBgY29sX25hbWVzID0gRmAsIOS4jeS9v+eUqOmmluihjOS9nOS4uuWIl+WQje+8jOWHveaVsOiHquWKqOWwhuWIl+agh+iusOS4ulgxLCBYMiwgLi4uDQogIC0gYGNvbF9uYW1lcyA9IOWtl+espuS4suWQkemHj2DvvIznm7TmjqXotYvliJflkI3np7ANCi0gYHNraXAgPSBuYCwg5b+955Wl5YmNbuihjO+8iOmAmuW4uOS4uk1ldGFEYXRh77yJDQotIGBjb21tZW50ID0gJyMnYCwg5b+955Wl5omA5pyJ5LulYCNg5byA5aS055qE6KGMDQotIGBuYSA9IGAsIOiuvuWumue8uuWkseWAvO+8jOm7mOiupOWQhOenjSB3aGl0ZSBzcGFjZVted2hpdGVTcGFjZV0g5ZKMYE5BYOmDveaYr+e8uuWkseWAvA0KDQpbXndoaXRlU3BhY2VdOiDlpoJgXG5g44CBYFx0YOetieeJueauiuWtl+espuOAgg0KDQoNCiMjIyBgcGFyc2VfKigpYA0KDQojIyMjIHJlYWRyIOino+aekOaWh+acrOaWh+S7tueahOWOn+eQhg0KDQrop6PmnpDkvp3pnaDlh73mlbDml49gcGFyc2VfKigpYOOAgui/meS6m+WHveaVsOaOpeWPl+S4gOS4quWtl+espuWQkemHj++8jOW5tui/lOWbnuS4gOS4queJueWumuWQkemHj++8jOWmgumAu+i+keOAgeaVtOaVsOaIluaXpeacn+WQkemHj+OAguWFt+S9k+adpeivtO+8jOmHjeimgeeahOino+aekOWHveaVsOaciSA4IOenjeOAgg0KDQoqIHBhcnNlX2xvZ2ljYWwoKeWSjHBhcnNlX2ludGVnZXIoKeWIhuWIq+ino+aekOmAu+i+keWAvOWSjOaVtOaVsOOAgui/meS4pOS4quino+aekOWHveaVsOWfuuacrOS4jeS8muWHuueOsOmXrumimA0KKiBwYXJzZV9kb3VibGUoKeaYr+S4peagvOeahOaVsOWAvOWei+ino+aekOWHveaVsO+8jHBhcnNlX251bWJlcigp5YiZ5piv54G15rS755qE5pWw5YC85Z6L6Kej5p6Q5Ye95pWw44CC6L+Z5Lik5Liq5Ye95pWw6KaB5q+U5L2g6aKE5oOz55qE5pu05aSN5p2C77yM5Zug5Li65LiW55WM5ZCE5Zyw5Lmm5YaZ5pWw5YC855qE5pa55byP5LiN5bC955u45ZCMICANCiogcGFyc2VfY2hhcmFjdGVyKCnkvLzkuY7lpKrov4fnroDljZXvvIznlJroh7PmsqHlv4XopoHlrZjlnKjjgILkvYbkuIDkuKrmo5jmiYvnmoTpl67popjkvb/lvpfov5nkuKrlh73mlbDlj5jlvpfpnZ7luLjph43opoHvvJrlrZfnrKbnvJbnoIENCiogcGFyc2VfZmFjdG9yKCnlh73mlbDlj6/ku6XliJvlu7rlm6DlrZDvvIxS5L2/55So6L+Z56eN5pWw5o2u57uT5p6E5p2l6KGo56S65YiG57G75Y+Y6YePICAgDQoqIHBhcnNlX2RhdGV0aW1lKCnjgIFwYXJzZV9kYXRlKCnlkoxwYXJzZV90aW1lKCnlh73mlbDlj6/ku6Xop6PmnpDkuI3lkIznsbvlnovnmoTml6XmnJ/lkozml7bpl7TjgILlroPku6zmmK/mnIDlpI3mnYLnmoTvvIzlm6DkuLrmnInlpKrlpJrkuI3lkIznmoTml6XmnJ/kuablhpnlvaLlvI8NCg0KKirmiYDku6Xor7vlj5YgY3N2IOi/nOavlOS9oOaDs+ixoeeahOWkjeadgu+8jOiHquW3semAoOi9ruWtkOS8mue0r+atu+OAgioqDQoNCiMjIyMg6Kej5p6Q5pWw5YC8DQoNCjEuIGBwYXJzZV9kb3VibGUoKWDnmoRgbG9jYWxlKGRlY2ltYWxfbWFyaz0pYOWPguaVsOWumuS5ieW9k+WcsOeahOWwj+aVsOeCueS5puWGmeW9ouW8j+OAgg0KYGBge3J9DQpwYXJzZV9kb3VibGUoIjMxMjEsMjMiLCBsb2NhbGUgPSBsb2NhbGUoZGVjaW1hbF9tYXJrID0gIiwiKSkNCmBgYA0KDQoNCjIuIGBwYXJzZV9udW1iZXIoKWDlj6/ku6Xlv73nlaXmlbDlgLzliY3lkI7nmoTpnZ7mlbDlgLzlnovlrZfnrKbjgILov5nkuKrlh73mlbDnibnliKvpgILlkIjlpITnkIbotKfluIHlkoznmb7liIbmr5TvvIzkuZ/lj6/ku6Xmj5Dlj5bltYzlnKjmlofmnKzkuK3nmoTmlbDlgLzjgIINCmBgYHtyfQ0KcGFyc2VfbnVtYmVyKCJJdCBjb3N0ICQxMjMuNDUuIikNCnBhcnNlX251bWJlcigiSSB3YW50IDQ1JSBvZiBpdC4iKQ0KYGBgDQoNCjMuIGBwYXJzZV9udW1iZXIoKWDlkoxgbG9jYWxlKGdyb3VwaW5nX21hcms9KWDlj4LmlbDlj6/ku6Xlv73nlaXkvY3mlbDpl7TpmpTnrKYoZ3JvdXBpbmcgbWFyaykNCmBgYHtyfQ0KcGFyc2VfbnVtYmVyKCIxMjMuNDU2Ljc4OSIsIGxvY2FsZSA9IGxvY2FsZShncm91cGluZ19tYXJrID0gIi4iKSkNCmBgYA0KDQojIyMjIOino+aekOWtl+espuS4sg0KDQrpnZ7oi7HmloflrZfnrKbnmoTnvJbnoIHmlrnlvI/mnInorrjlpJrnp43vvIzlr7nlhbbop6PnoIHpnIDopoHnlKhgbG9jYWxlKGVuY29kaW5nPSlg5Y+C5pWw6K6+572u57yW56CB5pa55byP77yMDQpgYGB7cn0NCngyIDwtICJceDgyXHhiMVx4ODJceGYxXHg4Mlx4YzlceDgyXHhiZlx4ODJceGNkIg0KcGFyc2VfY2hhcmFjdGVyKHgyLCBsb2NhbGUgPSBsb2NhbGUoZW5jb2RpbmcgPSAiU2hpZnQtSklTIikpDQpgYGANCg0KIyMjIyDop6PmnpDlm6DlrZANCmBgYHtyfQ0KZnJ1aXQgPC0gYygiYXBwbGUiLCAiYmFuYW5hIikNCnBhcnNlX2ZhY3RvcihjKCJhcHBsZSIsICJiYW5hbmEiLCAiYmFuYW5hbmEiKSwgbGV2ZWxzID0gZnJ1aXQpDQpgYGANCg0KIyMjIyAg6Kej5p6Q5pel5pyf5LiO5pe26Ze0DQoNCiogcGFyc2VfZGF0ZXRpbWUoKSDmjqXlj5fnrKblkIggSVNPIDg2MDEg5qCH5YeG55qE5pel5pyf5pe26Ze044CCDQoNCmBgYHtyfQ0KcGFyc2VfZGF0ZXRpbWUoIjIwMTAtMTAtMDFUMjAxMCIpDQoNCiMg5aaC5p6c5pe26Ze06KKr55yB55Wl5LqG77yM6YKj5LmI5a6D5bCx5Lya6KKr6K6+572u5Li65Y2I5aScMOeCuTDliIYNCnBhcnNlX2RhdGV0aW1lKCIyMDEwMTAxMCIpDQpgYGANCg0KKiBwYXJzZV9kYXRlKCkg5o6l5Y+X5piv5Zub5L2N5pWw55qE5bm05Lu9K2AtYOaIlmAvYCvmnIgrYC1g5oiWYC9gK+aXpQ0KYGBge3J9DQpwYXJzZV9kYXRlKCIyMDEwLTEwLTAxIikNCmBgYA0KDQoqIHBhcnNlX3RpbWUoKSDmjqXlj5flsI/ml7YrYDpgK+WIhumSnytbYDpgK+enkl0rW2FtL3BtXQ0KYGBge3J9DQpsaWJyYXJ5KGhtcykNCnBhcnNlX3RpbWUoIjAxOjEwIGFtIikNCnBhcnNlX3RpbWUoIjIwOjEwOjAxIikNCmBgYA0KDQoqIOiHquW3seiuvuWumuaXtumXtOagvOW8jw0KDQrnrKblj7d85ZCr5LmJICAgIA0KLS0tLXwtLS0tDQolWXw05L2N5pWw5bm05Lu9DQoleXwy5L2N5pWw5bm05Lu9KDAwLTY5IOKGkiAyMDAwLTIwNjksIDcwLTk5IOKGkiAxOTcwLTE5OTkpDQolbXwy5L2N5pWw5pyI5Lu9DQolYnznroDlhpnmnIjku70NCiVCfOaciOS7veWFqOensA0KJWR85pel5pyf77yM5LiA5L2N5pWw5oiW5Lik5L2N5pWwDQolZXzkuKTkvY3mlbDml6XmnJ8NCiVIfDAtMjPlsI/ml7YNCiVJJXB8MC0xMuWwj+aXtu+8jCVw6KGo56S6YW0vcG0NCiVNfOWIhumSnw0KJVN85pW05pWw56eSDQolT1N85a6e5pWw56eSDQolWnzml7bljLoNCiV6fOS4juWbvemZheagh+WHhuaXtumXtOeahOaXtuW3rg0KJS585b+955Wl5LiA5Liq6Z2e5pWw5YC85a2X56ymDQolKnzlv73nlaXmiYDmnInpnZ7mlbDlgLzlrZfnrKYNCg0K5rOo5oSP77yM6Iul5a+56Z2e6Iux6K+t5pyI5Lu95ZCN56ew5L2/55SoICViIOaIliAlQu+8jOmcgOimgeWcqGxvY2FsZSgp5Ye95pWw5Lit6K6+572u6K+t6KiA5Y+C5pWw44CCDQpgYGB7cn0NCnBhcnNlX2RhdGUoIjEgamFudmllciAyMDE1IiwgIiVkICVCICVZIiwgbG9jYWxlID0gbG9jYWxlKCJmciIpKQ0KYGBgDQoNCiMjIE91dHB1dA0KDQojIyMgdG8gQ29uc29sZQ0KDQpgY2F0KC4uLiAsIGZpbGUgPSAiIiwgc2VwID0gIiAiLCBmaWxsID0gRkFMU0UsIGxhYmVscyA9IE5VTEwsICBhcHBlbmQgPSBGQUxTRSlgCQ0KDQpmaWxlOuS4gOS4quaWh+S7tumTvuaOpeaIluiAheaWh+S7tuWQje+8jOWmguaenOS4jeWGmeatpOWPguaVsO+8jOihqOekuui+k+WHuuWIsOaOp+WItuWPsOOAgg0KDQpzZXA65YiG6ZqU56ymDQoNCmFwcGVuZDrmmK/lkKbov73liqDvvIzlvZPkuJTku4XlvZPlj4LmlbBmaWxl5piv5paH5Lu25ZCN6ICM6Z2e6ZO+5o6l5pe277yM5q2k5Y+C5pWw5omN5pyJ5pWI44CCCQ0KDQrms6jmhI/vvJpjYXQoKem7mOiupOeUqOepuuagvOWIhuW8gOWQhOmDqOWIhu+8jOS4jeS8muS7peaNouihjOS9nOS4uui+k+WHuueahOe7k+Wwvg0KDQoNCmBwcmludCgpYA0KDQrljLrliKvvvJpwcmludCgpIOi+k+WHuuWtl+espuS4suWQkemHj++8jGNhdCgpIOi+k+WHuuWtl+espuS4sueahOWGheWuue+8jOWwseWDj+aYvuekuuWcqOe9kemhteaIluaJk+WNsOe7k+aenOS4ig0KDQpgYGBSDQpyJD4gY2F0KCJIZWxsbyIpDQpIZWxsbw0KciQ+IHByaW50KCdIZWxsbycpDQpbMV0gIkhlbGxvIg0KYGBgDQoNCg0KIyMjIHRvIFRYVA0KDQpgcmVhZHI6OndyaXRlX2xpbmVzKClgDQoNCmBzaW5rKCJmaWxlbmFtZSIsIGFwcGVuZD1UUlVFLCBzcGxpdD1UUlVFKWAg5paH5pys6L6T5Ye677yM5piv5ZCm6L+95Yqg77yM5piv5ZCm5ZCM5pe26L6T5Ye65Zyo5bGP5bmV5LiKCQ0KDQpgc2luaygpYCDlj5bmtojmlofmnKzovpPlh7rliLDmlofku7YNCg0KDQojIyMgdG8gSlNPTg0KDQoxLiBganNvbmxpdGU6OnRvSlNPTigpYOS/neWtmOS4uiBKU09OIOWtl+espuS4sg0KMi4gYHJlYWRyOjp3cml0ZV9saW5lcyhkYXRhLCBwYXRoKWAg5L+d5a2Y5Li6IGpzb24g5paH5Lu2DQoNCmBgYHtyfQ0KZGlyLmNyZWF0ZSgiLi9kYXRhIikNCg0KaXJpcyAlPiUNCiAgaGVhZCgpICU+JQ0KICBqc29ubGl0ZTo6dG9KU09OKCkgJT4lDQogIHJlYWRyOjp3cml0ZV9saW5lcygiLi9kYXRhL2lyaXMuanNvbiIpDQpgYGANCg0KIyMjIHRvIC5yZGENCg0KYHNhdmUob2JqLCBmaWxlID0gJ3h4eC5yZGEnKWAg5L+d5a2Y5LiA5Lqb5Y+Y6YeP44CC56ys5LiA5Liq5Y+C5pWw55yB55Wl5pe25L+d5a2Y5omA5pyJ5a+56LGh44CCDQoNCmBzYXZlLmltYWdlKCd4eHgucmRhJylgIOS/neWtmOaVtOS4quW3peS9nOepuumXtOS4reeahOaJgOacieWPmOmHj+OAguWvueS6jumVv+acn+i/nue7ree8lueoi++8jOi/memdnuW4uOacieeUqOOAgg0KDQojIyMgdG8gLlJEUw0KDQpgc2F2ZVJEUygpYAnkv53lrZjljZXkuKrlr7nosaHliLDkuIDkuKpSRFPmlofku7YNCg0KIyMjIHRvIENTVg0KDQojIyMjIGBkYXRhLnRhYmxlOjpmd2lydGUoKWANCg0KIyMjIyBgcmVhZHI6OndyaXRlX2NzdigpYA0KDQrov5nkuKrlh73mlbDovpPlh7rnmoTmlofku7bog73lpJ/pobrliKnor7vlj5bnmoTmpoLnjofmm7Tpq5jvvIzlm6DkuLrvvJogIA0KDQoqIOWug+S7rOaAu+aYr+S9v+eUqFVURi04IOWvueWtl+espuS4sui/m+ihjOe8lueggSAgIA0KKiDlroPku6zkvb/nlKhJU08gODYwMeagvOW8j+adpeS/neWtmOaXpeacn+WSjOaXpeacn+aXtumXtOaVsOaNru+8jOS7peS+v+i/meS6m+aVsOaNruS4jeiuuuWcqOS9leenjeeOr+Wig+S4i+mDveabtOWuueaYk+ino+aekA0KDQrms6jmhI/vvIzlvZPkv53lrZjkuLpDU1bmlofku7bml7bvvIzliJfnmoTmlbDmja7nsbvlnovkv6Hmga/lsLHkuKLlpLHkuobvvJrov5nkvb/lvpdDU1bmlofku7blnKjmmoLlrZjkuLTml7bnu5Pmnpzml7bmnInkupvkuI3lj6/pnaDigJTigJTmr4/mrKHliqDovb3ml7bpg73opoHph43lu7rliJfnsbvlnovjgIINCg==