This document was created for a workshop I ran at NYU on using tidyverse in 2018. It contains explanations and examples of creating tidy data and using functions in dplyr() to manipulate data.

Outline

##Load packages

library(tidyverse)
library(stringr)

Tidy data

Is this table tidy?

No.

table2

Is this table tidy?

No.

table3

Is this table tidy?

Yes!

table1

Is this table tidy?

No.

gene_expression

Is this table tidy?

No.

facs_data

what are tidy data?

Jeff Leek in his book The Elements of Data Analytic Style summarizes the characteristics of tidy data as the points:

gather()

used when column names are not names of variables, but values of a variable (e.g. time). makes tables longer and skinny (previously known as melting)

gene_expression

gather()

used when column names are not names of variables, but values of a variable (e.g. time). makes tables longer and skinny (previously known as melting)

gather(gene_expression, t0:t2, key = "timepoint", value = "expression")

spread()

Spreading is the opposite of gathering. Used when an observation is scattered across multiple rows. spread() makes tables shorter and wider

facs_data

spread()

Spreading is the opposite of gathering. Used when an observation is scattered across multiple rows. spread() makes tables shorter and wider

spread(facs_data, key = Measure, value = Value)

Exercise 1

put table2 in tidy format

table2[1:6,] #truncated so it fits on slide
spread(table2, key = type, value = count)

Exercise 2

convert table1 to table2

table1
head(table2)
gather(table1, c(country, year, cases, population), key = "year", value = "count")

data import

readr() has numerous functions for reading in files as tibbles

Read in the annotation file for the yeast genome.

gff <- read_delim("Saccharomyces_cerevisiae.R64-1-1.34.gff3", 
    "\t", escape_double = FALSE, col_names = FALSE, 
    comment = "#", trim_ws = TRUE, skip = 24)

── Column specification ────────────────────────────────────────────────────────────────────────────────────────
cols(
  X1 = col_character(),
  X2 = col_character(),
  X3 = col_character(),
  X4 = col_double(),
  X5 = col_double(),
  X6 = col_character(),
  X7 = col_character(),
  X8 = col_character(),
  X9 = col_character()
)

Take a look at data

a tibble is a dataframe

head(gff)

Look at data structure with str()

str(gff)
spec_tbl_df [28,871 × 9] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ X1: chr [1:28871] "I" "I" "I" "I" ...
 $ X2: chr [1:28871] "SGD" "SGD" "SGD" "SGD" ...
 $ X3: chr [1:28871] "gene" "mRNA" "exon" "CDS" ...
 $ X4: num [1:28871] 335 335 335 335 538 ...
 $ X5: num [1:28871] 649 649 649 649 792 ...
 $ X6: chr [1:28871] "." "." "." "." ...
 $ X7: chr [1:28871] "+" "+" "+" "+" ...
 $ X8: chr [1:28871] "." "." "." "0" ...
 $ X9: chr [1:28871] "ID=gene:YAL069W;biotype=protein_coding;description=Dubious open reading frame%3B unlikely to encode a functiona"| __truncated__ "ID=transcript:YAL069W;Parent=gene:YAL069W;biotype=protein_coding;transcript_id=YAL069W" "Parent=transcript:YAL069W;Name=YAL069W.1;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=YAL069W.1;rank=1" "ID=CDS:YAL069W;Parent=transcript:YAL069W;protein_id=YAL069W" ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_character(),
  ..   X2 = col_character(),
  ..   X3 = col_character(),
  ..   X4 = col_double(),
  ..   X5 = col_double(),
  ..   X6 = col_character(),
  ..   X7 = col_character(),
  ..   X8 = col_character(),
  ..   X9 = col_character()
  .. )

Look at the data the tidyverse way

using glimpse()

glimpse(gff)
Rows: 28,871
Columns: 9
$ X1 <chr> "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I",…
$ X2 <chr> "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "…
$ X3 <chr> "gene", "mRNA", "exon", "CDS", "gene", "mRNA", "exon", "CDS", "gene", "mRNA", "exon", "CDS", "gene"…
$ X4 <dbl> 335, 335, 335, 335, 538, 538, 538, 538, 1807, 1807, 1807, 1807, 2480, 2480, 2480, 2480, 7235, 7235,…
$ X5 <dbl> 649, 649, 649, 649, 792, 792, 792, 792, 2169, 2169, 2169, 2169, 2707, 2707, 2707, 2707, 9016, 9016,…
$ X6 <chr> ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",…
$ X7 <chr> "+", "+", "+", "+", "+", "+", "+", "+", "-", "-", "-", "-", "+", "+", "+", "+", "-", "-", "-", "-",…
$ X8 <chr> ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0",…
$ X9 <chr> "ID=gene:YAL069W;biotype=protein_coding;description=Dubious open reading frame%3B unlikely to encod…

Assign meaningful names to columns

same approach as naming dataframe columns in base R

names(gff) <- c("chromosome", 
                "source", 
                "feature", 
                "start",
                "stop", 
                "unknown1",
                "strand",
                "unknown2",
                "info"
                )

Dataframe now has meaningful names

note that tidyverse tries to guess data type

glimpse(gff)
Rows: 28,871
Columns: 9
$ chromosome <chr> "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "I", "…
$ source     <chr> "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", …
$ feature    <chr> "gene", "mRNA", "exon", "CDS", "gene", "mRNA", "exon", "CDS", "gene", "mRNA", "exon", "CDS"…
$ start      <dbl> 335, 335, 335, 335, 538, 538, 538, 538, 1807, 1807, 1807, 1807, 2480, 2480, 2480, 2480, 723…
$ stop       <dbl> 649, 649, 649, 649, 792, 792, 792, 792, 2169, 2169, 2169, 2169, 2707, 2707, 2707, 2707, 901…
$ unknown1   <chr> ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "…
$ strand     <chr> "+", "+", "+", "+", "+", "+", "+", "+", "-", "-", "-", "-", "+", "+", "+", "+", "-", "-", "…
$ unknown2   <chr> ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", "…
$ info       <chr> "ID=gene:YAL069W;biotype=protein_coding;description=Dubious open reading frame%3B unlikely …

assign columns proper datatypes

assigning correct data type is critical for analyses and plotting with ggplot()

gff$feature = as.factor(gff$feature)
gff$chromosome = as.factor(gff$chromosome)
gff$strand = as.factor(gff$strand)
glimpse(gff)
Rows: 28,871
Columns: 9
$ chromosome <fct> I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I…
$ source     <chr> "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", "SGD", …
$ feature    <fct> gene, mRNA, exon, CDS, gene, mRNA, exon, CDS, gene, mRNA, exon, CDS, gene, mRNA, exon, CDS,…
$ start      <dbl> 335, 335, 335, 335, 538, 538, 538, 538, 1807, 1807, 1807, 1807, 2480, 2480, 2480, 2480, 723…
$ stop       <dbl> 649, 649, 649, 649, 792, 792, 792, 792, 2169, 2169, 2169, 2169, 2707, 2707, 2707, 2707, 901…
$ unknown1   <chr> ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "…
$ strand     <fct> +, +, +, +, +, +, +, +, -, -, -, -, +, +, +, +, -, -, -, -, +, +, +, +, -, -, -, -, +, +, +…
$ unknown2   <chr> ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", ".", "0", ".", ".", "…
$ info       <chr> "ID=gene:YAL069W;biotype=protein_coding;description=Dubious open reading frame%3B unlikely …

Select columns using select()

gff <- select(gff, c("chromosome", "feature", "start", "stop", "strand"))
head(gff)

Add a column with mutate()

gff <- mutate(gff, length = abs(start - stop))
head(gff)

Sort tibble by column with arrange()

Note that writing dplyr::arrange specifies the package and function if there is an overlay with functions in other packages or in base R.

dplyr::arrange(gff,length)

Sort by feature size with arrange()

sort largest to smallest using -

dplyr::arrange(gff,-length)

Analyze with summarize()

this creates a new tibble/dataframe

summarise(gff, mean = mean(length), 
               sd = sd(length), 
               min = min(length), 
               max = max(length)
          )

Analyze with summarize()

the function n() counts how many observations their are

summarise(gff, mean = mean(length), 
               sd = sd(length), 
               min = min(length), 
               max = max(length), 
               n = n())

using the pipe: %>%

Subset data with group_by()

gff %>%
mutate(length = abs(start - stop)) %>%
group_by(feature) %>%
summarise(mean = mean(length), sd = sd(length), min = min(length), max = max(length), n = n())

Filter rows with filter()

gff %>%
filter(feature != "mRNA" & feature != "rRNA_gene" & feature != "snoRNA_gene"& feature != "snRNA_gene") %>%
mutate(length = abs(start - stop)) %>%
group_by(feature) %>%
summarise(mean = mean(length), sd = sd(length), min = min(length), max = max(length), n = n()) 

Pass dataframe to ggplot for plotting

NOTE: ggplot uses + not the pipe %>%

gff %>%
filter(feature == c("CDS")) %>%
ggplot(aes(x = length)) + 
        geom_histogram(bins = 100)

Exercise 3

plot the population of each country in 1999 using %>% andggplot()`

table1

Exercise 3

table1 %>%
        select(-cases) %>%
        filter(year == "1999") %>%
        ggplot(mapping = aes(x = country, fill = country, y = population)) +
        geom_bar(stat="identity")

String manipulation with stringr()

How do we get the gene names?

select(gff, info)

Separate values in column with separate()

gff %>%
mutate(length = abs(start - stop)) %>%
filter(feature == "gene") %>%
separate(col = "info", into = c("info1", "info2", "info3", "info4", "info5"), sep = ";", extra = "merge") %>%
separate(col = "info1", into = c("junk", "Systematic_name"), sep = ":") %>%
separate(col = "info2", into = c("junk2", "Gene"), sep = "Name=") %>%
separate(col = "info3", into = c("junk3", "Description1"), sep = "description=") %>%  
separate(col = "info4", into = c("junk4", "Description2"), sep = "description=") %>%
select(c(Description1, Description2))

Combine columns with unite()

gff %>%
mutate(length = abs(start - stop)) %>%
filter(feature == "gene") %>%
separate(col = "info", into = c("info1", "info2", "info3", "info4", "info5"), sep = ";", extra = "merge") %>%
separate(col = "info1", into = c("junk", "Systematic_name"), sep = ":") %>%
separate(col = "info2", into = c("junk2", "Gene"), sep = "Name=") %>%
separate(col = "info3", into = c("junk3", "Description1"), sep = "description=") %>%  
separate(col = "info4", into = c("junk4", "Description2"), sep = "description=") %>%    
unite(Description, Description1, Description2, sep = ":") %>%
select(c(Description))

Save to a new variable

A general rule is if you are piping more than 10 steps save as a new variable

gff_clean <- gff %>%
mutate(length = abs(start - stop)) %>%
filter(feature == "gene") %>%
separate(col = "info", into = c("info1", "info2", "info3", "info4", "info5"), sep = ";", extra = "merge") %>%
separate(col = "info1", into = c("junk", "Systematic_name"), sep = ":") %>%
separate(col = "info2", into = c("junk2", "Gene"), sep = "Name=") %>%
separate(col = "info3", into = c("junk3", "Description1"), sep = "description=") %>%  
separate(col = "info4", into = c("junk4", "Description2"), sep = "description=") %>%    
unite(Description, Description1, Description2, sep = "") %>%
select(c(Systematic_name, Gene, Description))

Clean up strings with stringr()

gff_clean$Description <- str_replace_all(gff_clean$Description, "%3B", "")
gff_clean$Description <- str_replace_all(gff_clean$Description, "%2C", "")
gff_clean$Description <- str_replace_all(gff_clean$Description, "^NA", "")

gff_clean %>%
select(c(Description))
NA

Write file

write_tsv(gff_clean, "Yeast_genes.txt", na = "NA")

How do we combine tables?

Mutating joins

A mutating join allows you combine variables from two tables by matchiung observations by their keys

1. Inner Join

matches pairs of observation from two tables whenever their keys are equal

2. Outer join

keeps observations that appear in at least one of the tables

  • left join keeps all the observations in x (should be the default)
  • right join keeps all the observations in y
  • full join keeps all observations in x and y

3. Filtering joins

affects (filters) the observations not the variables

  • semi_join(x, y) keeps all observations in x that have a match in y
  • anti_join(x, y) drops all observations in x that have a match in y

Dataset must contain common values (gene names)

str(data)
spec_tbl_df [5,850 × 57] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Syst              : chr [1:5850] "Q0045" "Q0050" "Q0055" "Q0060" ...
 $ Gene              : chr [1:5850] "COX1" "AI1" "AI2" "AI3" ...
 $ CodingLength      : num [1:5850] 3.21 3.4 3.41 3.1 3.22 ...
 $ X3primeUTRLength  : num [1:5850] 2.04 NA NA NA 2.33 ...
 $ X5primeUTRLength  : num [1:5850] NA NA NA NA NA ...
 $ X5primeUTR_GC     : num [1:5850] NA NA NA NA NA ...
 $ X3primeUTR_GC     : num [1:5850] 0.055 NA NA NA 0.234 ...
 $ mRNA_abundance    : num [1:5850] -1.65 -1.64 -2.22 -2.74 -2.74 ...
 $ Protein_per_cell  : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Ribosome_density  : num [1:5850] NA NA NA NA NA ...
 $ Transcription_Rate: num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ codingGCposition1 : num [1:5850] 0.381 0.309 0.311 0.305 0.309 0.303 0.268 0.204 0.285 0.36 ...
 $ codingGCposition2 : num [1:5850] 0.372 0.329 0.329 0.284 0.312 0.309 0.2 0.204 0.315 0.332 ...
 $ WobbleGC          : num [1:5850] 0.144 0.11 0.156 0.06 0.083 0.074 0.028 0.163 0.112 0.14 ...
 $ Protein_halflife  : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ deltaG            : num [1:5850] -480 -661 -756 -309 -449 ...
 $ CAI               : num [1:5850] -0.853 -0.911 -0.807 -0.915 -0.916 ...
 $ nTE               : num [1:5850] 0.152 0.134 0.144 0.128 0.133 ...
 $ Protein_per_mRNA  : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Munchel           : num [1:5850] 0.0354 NA 0.0378 0.0334 0.0301 ...
 $ Miller            : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Wang              : num [1:5850] 0.00815 0.01136 0.01386 0.00866 0.00856 ...
 $ Grigul            : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Garcia_Martinez   : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Shalem            : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Presnyak          : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Neymotin          : num [1:5850] NA 0.0561 0.0368 0.0842 NA NA 0.0857 NA NA 0.0205 ...
 $ Bfr1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Cbc2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Cbf5              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Gbp2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Hrb1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Khd1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Msl5              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Nab2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Nab3              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Nab6              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Npl3              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Nrd1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Nsr1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Pab1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Pin4              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Pub1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Puf1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Puf2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Puf3              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Puf4              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Puf5              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Scp160            : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Sik1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Ski2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Ssd1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Tdh3              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Vts1              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Yll032c           : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Ypl184c           : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 $ Yra2              : num [1:5850] NA NA NA NA NA NA NA NA NA NA ...
 - attr(*, "spec")=
  .. cols(
  ..   Syst = col_character(),
  ..   Gene = col_character(),
  ..   CodingLength = col_double(),
  ..   X3primeUTRLength = col_double(),
  ..   X5primeUTRLength = col_double(),
  ..   X5primeUTR_GC = col_double(),
  ..   X3primeUTR_GC = col_double(),
  ..   mRNA_abundance = col_double(),
  ..   Protein_per_cell = col_double(),
  ..   Ribosome_density = col_double(),
  ..   Transcription_Rate = col_double(),
  ..   codingGCposition1 = col_double(),
  ..   codingGCposition2 = col_double(),
  ..   WobbleGC = col_double(),
  ..   Protein_halflife = col_double(),
  ..   deltaG = col_double(),
  ..   CAI = col_double(),
  ..   nTE = col_double(),
  ..   Protein_per_mRNA = col_double(),
  ..   Munchel = col_double(),
  ..   Miller = col_double(),
  ..   Wang = col_double(),
  ..   Grigul = col_double(),
  ..   Garcia_Martinez = col_double(),
  ..   Shalem = col_double(),
  ..   Presnyak = col_double(),
  ..   Neymotin = col_double(),
  ..   Bfr1 = col_double(),
  ..   Cbc2 = col_double(),
  ..   Cbf5 = col_double(),
  ..   Gbp2 = col_double(),
  ..   Hrb1 = col_double(),
  ..   Khd1 = col_double(),
  ..   Msl5 = col_double(),
  ..   Nab2 = col_double(),
  ..   Nab3 = col_double(),
  ..   Nab6 = col_double(),
  ..   Npl3 = col_double(),
  ..   Nrd1 = col_double(),
  ..   Nsr1 = col_double(),
  ..   Pab1 = col_double(),
  ..   Pin4 = col_double(),
  ..   Pub1 = col_double(),
  ..   Puf1 = col_double(),
  ..   Puf2 = col_double(),
  ..   Puf3 = col_double(),
  ..   Puf4 = col_double(),
  ..   Puf5 = col_double(),
  ..   Scp160 = col_double(),
  ..   Sik1 = col_double(),
  ..   Ski2 = col_double(),
  ..   Ssd1 = col_double(),
  ..   Tdh3 = col_double(),
  ..   Vts1 = col_double(),
  ..   Yll032c = col_double(),
  ..   Ypl184c = col_double(),
  ..   Yra2 = col_double()
  .. )

File to join with

str(gff_clean)
tibble [6,692 × 3] (S3: tbl_df/tbl/data.frame)
 $ Systematic_name: chr [1:6692] "YAL069W" "YAL068W-A" "YAL068C" "YAL067W-A" ...
 $ Gene           : chr [1:6692] NA NA "PAU8" NA ...
 $ Description    : chr [1:6692] "Dubious open reading frame unlikely to encode a functional protein based on available experimental and comparat"| __truncated__ "Dubious open reading frame unlikely to encode a functional protein based on available experimental and comparat"| __truncated__ "Protein of unknown function member of the seripauperin multigene family encoded mainly in subtelomeric regions "| __truncated__ "Putative protein of unknown function identified by gene-trapping microarray-based expression analysis and genom"| __truncated__ ...

Joining data

dplyr::left_join(a, b, by = "x1") Join matching rows from b to a.

left_join(gff_clean, data, by = c("Systematic_name" = "Syst")) %>%
        str()
tibble [6,695 × 59] (S3: tbl_df/tbl/data.frame)
 $ Systematic_name   : chr [1:6695] "YAL069W" "YAL068W-A" "YAL068C" "YAL067W-A" ...
 $ Gene.x            : chr [1:6695] NA NA "PAU8" NA ...
 $ Description       : chr [1:6695] "Dubious open reading frame unlikely to encode a functional protein based on available experimental and comparat"| __truncated__ "Dubious open reading frame unlikely to encode a functional protein based on available experimental and comparat"| __truncated__ "Protein of unknown function member of the seripauperin multigene family encoded mainly in subtelomeric regions "| __truncated__ "Putative protein of unknown function identified by gene-trapping microarray-based expression analysis and genom"| __truncated__ ...
 $ Gene.y            : chr [1:6695] NA NA "PAU8" "YAL067W-A" ...
 $ CodingLength      : num [1:6695] NA NA 2.56 2.36 3.25 ...
 $ X3primeUTRLength  : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ X5primeUTRLength  : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ X5primeUTR_GC     : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ X3primeUTR_GC     : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ mRNA_abundance    : num [1:6695] NA NA NA -2.92082 0.00423 ...
 $ Protein_per_cell  : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ Ribosome_density  : num [1:6695] NA NA NA NA 2.23 ...
 $ Transcription_Rate: num [1:6695] NA NA NA NA NA ...
 $ codingGCposition1 : num [1:6695] NA NA 0.488 0.421 0.396 NA 0.38 0.63 0.48 0.432 ...
 $ codingGCposition2 : num [1:6695] NA NA 0.471 0.368 0.357 NA 0.581 0.362 0.449 0.347 ...
 $ WobbleGC          : num [1:6695] NA NA 0.529 0.447 0.33 NA 0.364 0.37 0.386 0.326 ...
 $ Protein_halflife  : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ deltaG            : num [1:6695] NA NA -110.9 -63.4 -569.7 ...
 $ CAI               : num [1:6695] NA NA -0.202 -1.178 -0.735 ...
 $ nTE               : num [1:6695] NA NA 0.241 0.142 0.161 ...
 $ Protein_per_mRNA  : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ Munchel           : num [1:6695] NA NA 0.061 NA NA ...
 $ Miller            : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ Wang              : num [1:6695] NA NA NA NA NA ...
 $ Grigul            : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ Garcia_Martinez   : num [1:6695] NA NA NA NA NA ...
 $ Shalem            : num [1:6695] NA NA 0.00869 0.02155 0.02005 ...
 $ Presnyak          : num [1:6695] NA NA NA NA NA NA NA NA NA NA ...
 $ Neymotin          : num [1:6695] NA NA NA NA NA ...
 $ Bfr1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Cbc2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Cbf5              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Gbp2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Hrb1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Khd1              : num [1:6695] NA NA 0 NA 0 NA 1 0 1 0 ...
 $ Msl5              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Nab2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Nab3              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Nab6              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Npl3              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Nrd1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Nsr1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Pab1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Pin4              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Pub1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Puf1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Puf2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Puf3              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Puf4              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Puf5              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Scp160            : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Sik1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Ski2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Ssd1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Tdh3              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Vts1              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Yll032c           : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Ypl184c           : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...
 $ Yra2              : num [1:6695] NA NA 0 NA 0 NA 0 0 0 0 ...

Exercise 4

tidy data don’t allow easy correlation plots, so we need to rearrage the data

tidy_gene_expression <- gene_expression %>%
        gather(t0:t2, key = "timepoint", value = "expression")
tidy_gene_expression

Rearrange the data

Plot correlation between t0 and t1

Exercise 5

Example

ggplot(data = yeast_features, mapping = aes(x = chromosome, fill = feature)) +
        geom_bar(position = "dodge")

Resources

LS0tCnRpdGxlOiAidGlkeXZlcnNlIgphdXRob3I6ICJEYXZpZCBHcmVzaGFtIgpkYXRlOiBMYXN0IGNvbXBpbGVkIG9uICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHllcwotLS0KClRoaXMgZG9jdW1lbnQgd2FzIGNyZWF0ZWQgZm9yIGEgd29ya3Nob3AgSSByYW4gYXQgTllVIG9uIHVzaW5nIHRpZHl2ZXJzZSBpbiAyMDE4LiAgSXQgY29udGFpbnMgZXhwbGFuYXRpb25zIGFuZCBleGFtcGxlcyBvZiBjcmVhdGluZyB0aWR5IGRhdGEgYW5kIHVzaW5nIGZ1bmN0aW9ucyBpbiBgZHBseXIoKWAgdG8gbWFuaXB1bGF0ZSBkYXRhLiAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoja25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkKYGBgCgojIyBPdXRsaW5lCgoqIHRpZHkgZGF0YQoqIHJlYWRpbmcgZGF0YQoqIHZlcmJzIGluIGRwbHlyKCkKICAgICsgYHNlbGVjdCgpYAogICAgKyBgbXV0YXRlKClgCiAgICArIGBhcnJhbmdlKClgCiAgICArIGBzdW1tYXJpc2UoKWAKICAgICsgYGZpbHRlcigpYAoqIHRoZSBwaXBlIGAlPiVgCiogam9pbmluZyBmaWxlcwoKIyNMb2FkIHBhY2thZ2VzCgpgYGB7ciwgZWNobyA9IFR9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHN0cmluZ3IpCmBgYAoKIyMgVGlkeSBkYXRhCiogZWFjaCBfX3ZhcmlhYmxlX18gaXMgc2F2ZWQgaW4gaXRzIG9uIF9fY29sdW1uX18KKiBlYWNoIF9fb2JzZXJ2YXRpb25fXyBpcyBzYXZlZCBpbiBpdHMgb3duIF9fcm93X18KKiBlYWNoIF9fdmFsdWVfXyBtdXN0IGhhdmUgaXRzIG93biBfX2NlbGxfXwoKYGBge3IgZWNobz1GQUxTRSwgZmlnLndpZHRoPTYsIGZpZy5hc3AgPSAwLjYxOCwgb3V0LndpZHRoID0gIjcwJSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCB3YXJuaW5nPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9pbWFnZXMvdGlkeS0xLnBuZyIpCmBgYAoKIyMgSXMgdGhpcyB0YWJsZSB0aWR5PwpOby4KYGBge3J9CnRhYmxlMgpgYGAKCiMjIElzIHRoaXMgdGFibGUgdGlkeT8KTm8uCmBgYHtyfQp0YWJsZTMKYGBgCgojIyBJcyB0aGlzIHRhYmxlIHRpZHk/ClllcyEKYGBge3J9CnRhYmxlMQpgYGAKCiMjIElzIHRoaXMgdGFibGUgdGlkeT8KTm8uCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmdlbmVfZXhwcmVzc2lvbiA8LSB0aWJibGUoCiAgICAgICAgR2VuZSA9IGMoIkFDVDEiLCAiR0FQMSIsICJNRVAyIiwgIkRVUjMiLCAiTVNOMiIsICJEQUw4MCIpLAogICAgICAgIHQwID0gYygyLjIsIDQuMywgMS42LCAtMS4yLCAtMi4wLCAwLjIpLAogICAgICAgIHQxID0gYygzLjIsIDIuMSwgMC44LCAtMS44LCAtMC44LCAwLjYpLAogICAgICAgIHQyID0gYyg0LjUsIDEuNiwgMC40LCAtMS44LCAtMC4xLCAwLjkpCikKCmBgYAoKYGBge3J9CmdlbmVfZXhwcmVzc2lvbgpgYGAKCiMjIElzIHRoaXMgdGFibGUgdGlkeT8KTm8uCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmZhY3NfZGF0YSA8LSB0aWJibGUoCiAgICAgICAgU2FtcGxlID0gYygiQTEiLCAiQTEiLCAiQTIiLCAiQTIiLCAiQTMiLCAiQTMiKSwKICAgICAgICBNZWFzdXJlID0gYygiRlNDIiwgIkZMMSIsICJGU0MiLCAiRkwxIiwgIkZTQyIsICJGTDEiKSwKICAgICAgICBWYWx1ZSA9IGMoMy42LCA0LjUsIDMuNSwgMy4yLCAzLjgsIDQuMikKKQoKYGBgCgpgYGB7cn0KZmFjc19kYXRhCmBgYAoKIyMgd2hhdCBhcmUgdGlkeSBkYXRhPwoKSmVmZiBMZWVrIGluIGhpcyBib29rIF9fVGhlIEVsZW1lbnRzIG9mIERhdGEgQW5hbHl0aWMgU3R5bGVfXyBzdW1tYXJpemVzIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGlkeSBkYXRhIGFzIHRoZSBwb2ludHM6CgoqIEVhY2ggdmFyaWFibGUgeW91IG1lYXN1cmUgc2hvdWxkIGJlIGluIG9uZSBjb2x1bW4uCiogRWFjaCBkaWZmZXJlbnQgb2JzZXJ2YXRpb24gb2YgdGhhdCB2YXJpYWJsZSBzaG91bGQgYmUgaW4gYSBkaWZmZXJlbnQgcm93LgoqIFRoZXJlIHNob3VsZCBiZSBvbmUgdGFibGUgZm9yIGVhY2ggImtpbmQiIG9mIHZhcmlhYmxlLgoqIElmIHlvdSBoYXZlIG11bHRpcGxlIHRhYmxlcywgdGhleSBzaG91bGQgaW5jbHVkZSBhIGNvbHVtbiBpbiB0aGUgdGFibGUgdGhhdCBhbGxvd3MgdGhlbSB0byBiZSBsaW5rZWQuCgpbaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVGlkeV9kYXRhXTogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVGlkeV9kYXRhCgoKIyMgZ2F0aGVyKCkKdXNlZCB3aGVuIGNvbHVtbiBuYW1lcyBhcmUgbm90IG5hbWVzIG9mIHZhcmlhYmxlcywgYnV0IF92YWx1ZXNfIG9mIGEgdmFyaWFibGUgKGUuZy4gdGltZSkuCm1ha2VzIHRhYmxlcyBfbG9uZ2VyXyBhbmQgX3NraW5ueV8gKHByZXZpb3VzbHkga25vd24gYXMgbWVsdGluZykKYGBge3J9CmdlbmVfZXhwcmVzc2lvbgpgYGAKCgojIyBnYXRoZXIoKQp1c2VkIHdoZW4gY29sdW1uIG5hbWVzIGFyZSBub3QgbmFtZXMgb2YgdmFyaWFibGVzLCBidXQgX3ZhbHVlc18gb2YgYSB2YXJpYWJsZSAoZS5nLiB0aW1lKS4KbWFrZXMgdGFibGVzIF9sb25nZXJfIGFuZCBfc2tpbm55XyAocHJldmlvdXNseSBrbm93biBhcyBtZWx0aW5nKQpgYGB7cn0KZ2F0aGVyKGdlbmVfZXhwcmVzc2lvbiwgdDA6dDIsIGtleSA9ICJ0aW1lcG9pbnQiLCB2YWx1ZSA9ICJleHByZXNzaW9uIikKYGBgCgojIyBzcHJlYWQoKQpTcHJlYWRpbmcgaXMgdGhlIG9wcG9zaXRlIG9mIGdhdGhlcmluZy4gIFVzZWQgd2hlbiBhbiBvYnNlcnZhdGlvbiBpcyBzY2F0dGVyZWQgYWNyb3NzIG11bHRpcGxlIHJvd3MuCmBzcHJlYWQoKWAgbWFrZXMgdGFibGVzIF9zaG9ydGVyXyBhbmQgX3dpZGVyXwpgYGB7cn0KZmFjc19kYXRhCmBgYAoKIyMgc3ByZWFkKCkKU3ByZWFkaW5nIGlzIHRoZSBvcHBvc2l0ZSBvZiBnYXRoZXJpbmcuICBVc2VkIHdoZW4gYW4gb2JzZXJ2YXRpb24gaXMgc2NhdHRlcmVkIGFjcm9zcyBtdWx0aXBsZSByb3dzLgpgc3ByZWFkKClgIG1ha2VzIHRhYmxlcyBfc2hvcnRlcl8gYW5kIF93aWRlcl8KYGBge3J9CnNwcmVhZChmYWNzX2RhdGEsIGtleSA9IE1lYXN1cmUsIHZhbHVlID0gVmFsdWUpCmBgYAoKIyMgRXhlcmNpc2UgMQpwdXQgdGFibGUyIGluIHRpZHkgZm9ybWF0CmBgYHtyfQp0YWJsZTJbMTo2LF0gI3RydW5jYXRlZCBzbyBpdCBmaXRzIG9uIHNsaWRlCmBgYAoKYGBge3J9CnNwcmVhZCh0YWJsZTIsIGtleSA9IHR5cGUsIHZhbHVlID0gY291bnQpCmBgYAoKIyMgRXhlcmNpc2UgMgpjb252ZXJ0IHRhYmxlMSB0byB0YWJsZTIKYGBge3J9CnRhYmxlMQpgYGAKCmBgYHtyfQpoZWFkKHRhYmxlMikKYGBgCgoKYGBge3J9CmdhdGhlcih0YWJsZTEsIGMoY291bnRyeSwgeWVhciwgY2FzZXMsIHBvcHVsYXRpb24pLCBrZXkgPSAieWVhciIsIHZhbHVlID0gImNvdW50IikKYGBgCgoKIyMgZGF0YSBpbXBvcnQKYHJlYWRyKClgIGhhcyBudW1lcm91cyBmdW5jdGlvbnMgZm9yIHJlYWRpbmcgaW4gZmlsZXMgYXMgdGliYmxlcwoKKyBgcmVhZF9jc3YoKWAgZm9yIGNvbW1hLWRlbGltaXRlZAorIGByZWFkX3RzdigpYCBmb3IgdGFiLWRlbGltaXRlZAorIGByZWFkX2RlbGltKClgIGluIHdoaWNoIHlvdSBzcGVjaWZ5IHRoZSBkZWxpbWl0ZXIKClJlYWQgaW4gdGhlIGFubm90YXRpb24gZmlsZSBmb3IgdGhlIHllYXN0IGdlbm9tZS4KYGBge3IgZGF0YX0KZ2ZmIDwtIHJlYWRfZGVsaW0oIlNhY2NoYXJvbXljZXNfY2VyZXZpc2lhZS5SNjQtMS0xLjM0LmdmZjMiLCAKICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsIAogICAgY29tbWVudCA9ICIjIiwgdHJpbV93cyA9IFRSVUUsIHNraXAgPSAyNCkKYGBgCgojIyBUYWtlIGEgbG9vayBhdCBkYXRhCgphIHRpYmJsZSBpcyBhIGRhdGFmcmFtZQoKYGBge3J9CmhlYWQoZ2ZmKQpgYGAKCiMjIExvb2sgYXQgZGF0YSBzdHJ1Y3R1cmUgd2l0aCBzdHIoKQpgYGB7cn0Kc3RyKGdmZikKYGBgCgojIyBMb29rIGF0IHRoZSBkYXRhIHRoZSB0aWR5dmVyc2Ugd2F5CiMjIyB1c2luZyBnbGltcHNlKCkKCmBgYHtyfQpnbGltcHNlKGdmZikKYGBgCgojIyBBc3NpZ24gbWVhbmluZ2Z1bCBuYW1lcyB0byBjb2x1bW5zCnNhbWUgYXBwcm9hY2ggYXMgbmFtaW5nIGRhdGFmcmFtZSBjb2x1bW5zIGluIGJhc2UgUgpgYGB7cn0KbmFtZXMoZ2ZmKSA8LSBjKCJjaHJvbW9zb21lIiwgCiAgICAgICAgICAgICAgICAic291cmNlIiwgCiAgICAgICAgICAgICAgICAiZmVhdHVyZSIsIAogICAgICAgICAgICAgICAgInN0YXJ0IiwKICAgICAgICAgICAgICAgICJzdG9wIiwgCiAgICAgICAgICAgICAgICAidW5rbm93bjEiLAogICAgICAgICAgICAgICAgInN0cmFuZCIsCiAgICAgICAgICAgICAgICAidW5rbm93bjIiLAogICAgICAgICAgICAgICAgImluZm8iCiAgICAgICAgICAgICAgICApCmBgYAoKIyMgRGF0YWZyYW1lIG5vdyBoYXMgbWVhbmluZ2Z1bCBuYW1lcwpub3RlIHRoYXQgdGlkeXZlcnNlIHRyaWVzIHRvIGd1ZXNzIGRhdGEgdHlwZQpgYGB7cn0KZ2xpbXBzZShnZmYpCmBgYAoKIyMgYXNzaWduIGNvbHVtbnMgcHJvcGVyIGRhdGF0eXBlcwphc3NpZ25pbmcgY29ycmVjdCBkYXRhIHR5cGUgaXMgY3JpdGljYWwgZm9yIGFuYWx5c2VzIGFuZCBwbG90dGluZyB3aXRoIGdncGxvdCgpCmBgYHtyfQpnZmYkZmVhdHVyZSA9IGFzLmZhY3RvcihnZmYkZmVhdHVyZSkKZ2ZmJGNocm9tb3NvbWUgPSBhcy5mYWN0b3IoZ2ZmJGNocm9tb3NvbWUpCmdmZiRzdHJhbmQgPSBhcy5mYWN0b3IoZ2ZmJHN0cmFuZCkKZ2xpbXBzZShnZmYpCmBgYAoKIyMgU2VsZWN0IGNvbHVtbnMgdXNpbmcgYHNlbGVjdCgpYApgYGB7cn0KZ2ZmIDwtIHNlbGVjdChnZmYsIGMoImNocm9tb3NvbWUiLCAiZmVhdHVyZSIsICJzdGFydCIsICJzdG9wIiwgInN0cmFuZCIpKQpoZWFkKGdmZikKYGBgCgojIyBBZGQgYSBjb2x1bW4gd2l0aCBgbXV0YXRlKClgCmBgYHtyfQpnZmYgPC0gbXV0YXRlKGdmZiwgbGVuZ3RoID0gYWJzKHN0YXJ0IC0gc3RvcCkpCmhlYWQoZ2ZmKQpgYGAKCiMjIFNvcnQgdGliYmxlIGJ5IGNvbHVtbiB3aXRoIGBhcnJhbmdlKClgCk5vdGUgdGhhdCB3cml0aW5nIGBkcGx5cjo6YXJyYW5nZWAgc3BlY2lmaWVzIHRoZSBwYWNrYWdlIGFuZCBmdW5jdGlvbiBpZiB0aGVyZSBpcyBhbiBvdmVybGF5IHdpdGggZnVuY3Rpb25zIGluIG90aGVyIHBhY2thZ2VzIG9yIGluIGJhc2UgUi4gCmBgYHtyfQpkcGx5cjo6YXJyYW5nZShnZmYsbGVuZ3RoKQpgYGAKCiMjIFNvcnQgYnkgZmVhdHVyZSBzaXplIHdpdGggYXJyYW5nZSgpCnNvcnQgbGFyZ2VzdCB0byBzbWFsbGVzdCB1c2luZyBgLWAKYGBge3J9CmRwbHlyOjphcnJhbmdlKGdmZiwtbGVuZ3RoKQpgYGAKCiMjIEFuYWx5emUgd2l0aCBgc3VtbWFyaXplKClgCnRoaXMgY3JlYXRlcyBhIG5ldyB0aWJibGUvZGF0YWZyYW1lIApgYGB7cn0Kc3VtbWFyaXNlKGdmZiwgbWVhbiA9IG1lYW4obGVuZ3RoKSwgCiAgICAgICAgICAgICAgIHNkID0gc2QobGVuZ3RoKSwgCiAgICAgICAgICAgICAgIG1pbiA9IG1pbihsZW5ndGgpLCAKICAgICAgICAgICAgICAgbWF4ID0gbWF4KGxlbmd0aCkKICAgICAgICAgICkKYGBgCgojIyBBbmFseXplIHdpdGggYHN1bW1hcml6ZSgpYAp0aGUgZnVuY3Rpb24gYG4oKWAgY291bnRzIGhvdyBtYW55IG9ic2VydmF0aW9ucyB0aGVpciBhcmUKYGBge3J9CnN1bW1hcmlzZShnZmYsIG1lYW4gPSBtZWFuKGxlbmd0aCksIAogICAgICAgICAgICAgICBzZCA9IHNkKGxlbmd0aCksIAogICAgICAgICAgICAgICBtaW4gPSBtaW4obGVuZ3RoKSwgCiAgICAgICAgICAgICAgIG1heCA9IG1heChsZW5ndGgpLCAKICAgICAgICAgICAgICAgbiA9IG4oKSkKYGBgCgojIyB1c2luZyB0aGUgcGlwZTogYCU+JWAKKyB0aGUgcGlwZSBpcyBmcm9tIHRoZSBgbWFnaXR0cmAgcGFja2FnZQorIHNhbWUgYXMgYHxgIGluIHVuaXgKKyBhbGxvd3MgeW91IHRvIHBlcmZvcm0gbXVsdGlwbGUgc2VxdWVudGlhbCBmdW5jdGlvbnMKKyBwcm9ub3VuY2VkIF9fdGhlbl9fCisgdW5sZWFzaGVzIHRoZSB0cnVlIHBvd2VyIG9mIHRpZHl2ZXJzZSBmdW5jdGlvbnMKCgojIyBTdWJzZXQgZGF0YSB3aXRoIGBncm91cF9ieSgpYApgYGB7cn0KZ2ZmICU+JQptdXRhdGUobGVuZ3RoID0gYWJzKHN0YXJ0IC0gc3RvcCkpICU+JQpncm91cF9ieShmZWF0dXJlKSAlPiUKc3VtbWFyaXNlKG1lYW4gPSBtZWFuKGxlbmd0aCksIHNkID0gc2QobGVuZ3RoKSwgbWluID0gbWluKGxlbmd0aCksIG1heCA9IG1heChsZW5ndGgpLCBuID0gbigpKQpgYGAKCiMjIEZpbHRlciByb3dzIHdpdGggYGZpbHRlcigpYApgYGB7cn0KZ2ZmICU+JQpmaWx0ZXIoZmVhdHVyZSAhPSAibVJOQSIgJiBmZWF0dXJlICE9ICJyUk5BX2dlbmUiICYgZmVhdHVyZSAhPSAic25vUk5BX2dlbmUiJiBmZWF0dXJlICE9ICJzblJOQV9nZW5lIikgJT4lCm11dGF0ZShsZW5ndGggPSBhYnMoc3RhcnQgLSBzdG9wKSkgJT4lCmdyb3VwX2J5KGZlYXR1cmUpICU+JQpzdW1tYXJpc2UobWVhbiA9IG1lYW4obGVuZ3RoKSwgc2QgPSBzZChsZW5ndGgpLCBtaW4gPSBtaW4obGVuZ3RoKSwgbWF4ID0gbWF4KGxlbmd0aCksIG4gPSBuKCkpIApgYGAKCiMjIFBhc3MgZGF0YWZyYW1lIHRvIGdncGxvdCBmb3IgcGxvdHRpbmcKX19OT1RFOiBnZ3Bsb3QgdXNlcyBgK2Agbm90IHRoZSBwaXBlIGAlPiVgX18KYGBge3IsIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTJ9CmdmZiAlPiUKZmlsdGVyKGZlYXR1cmUgPT0gYygiQ0RTIikpICU+JQpnZ3Bsb3QoYWVzKHggPSBsZW5ndGgpKSArIAogICAgICAgIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxMDApCmBgYAoKIyMgRXhlcmNpc2UgMwpwbG90IHRoZSBwb3B1bGF0aW9uIG9mIGVhY2ggY291bnRyeSBpbiAxOTk5IHVzaW5nIGAlPiUgYW5kICBgZ2dwbG90KClgCmBgYHtyfQp0YWJsZTEKYGBgCgojIyBFeGVyY2lzZSAzCmBgYHtyfQp0YWJsZTEgJT4lCiAgICAgICAgc2VsZWN0KC1jYXNlcykgJT4lCiAgICAgICAgZmlsdGVyKHllYXIgPT0gIjE5OTkiKSAlPiUKICAgICAgICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gY291bnRyeSwgZmlsbCA9IGNvdW50cnksIHkgPSBwb3B1bGF0aW9uKSkgKwogICAgICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKYGBgCgoKIyMgU3RyaW5nIG1hbmlwdWxhdGlvbiB3aXRoIGBzdHJpbmdyKClgCkhvdyBkbyB3ZSBnZXQgdGhlIGdlbmUgbmFtZXM/CmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnZmYgPC0gcmVhZF9kZWxpbSgiU2FjY2hhcm9teWNlc19jZXJldmlzaWFlLlI2NC0xLTEuMzQuZ2ZmMyIsIAogICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBGQUxTRSwgCiAgICBjb21tZW50ID0gIiMiLCB0cmltX3dzID0gVFJVRSwgc2tpcCA9IDI0KQoKbmFtZXMoZ2ZmKSA8LSBjKCJjaHJvbW9zb21lIiwgCiAgICAgICAgICAgICAgICAic291cmNlIiwgCiAgICAgICAgICAgICAgICAiZmVhdHVyZSIsIAogICAgICAgICAgICAgICAgInN0YXJ0IiwKICAgICAgICAgICAgICAgICJzdG9wIiwgCiAgICAgICAgICAgICAgICAidW5rbm93bjEiLAogICAgICAgICAgICAgICAgInN0cmFuZCIsCiAgICAgICAgICAgICAgICAidW5rbm93bjIiLAogICAgICAgICAgICAgICAgImluZm8iCiAgICAgICAgICAgICAgICApCgpnZmYkZmVhdHVyZSA9IGFzLmZhY3RvcihnZmYkZmVhdHVyZSkKZ2ZmJGNocm9tb3NvbWUgPSBhcy5mYWN0b3IoZ2ZmJGNocm9tb3NvbWUpCmdmZiRzdHJhbmQgPSBhcy5mYWN0b3IoZ2ZmJHN0cmFuZCkKYGBgCgpgYGB7cn0Kc2VsZWN0KGdmZiwgaW5mbykKYGBgCgoKIyMgU2VwYXJhdGUgdmFsdWVzIGluIGNvbHVtbiB3aXRoIGBzZXBhcmF0ZSgpYCB7LnNtYWxsZXJ9CmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpnZmYgJT4lCm11dGF0ZShsZW5ndGggPSBhYnMoc3RhcnQgLSBzdG9wKSkgJT4lCmZpbHRlcihmZWF0dXJlID09ICJnZW5lIikgJT4lCnNlcGFyYXRlKGNvbCA9ICJpbmZvIiwgaW50byA9IGMoImluZm8xIiwgImluZm8yIiwgImluZm8zIiwgImluZm80IiwgImluZm81IiksIHNlcCA9ICI7IiwgZXh0cmEgPSAibWVyZ2UiKSAlPiUKc2VwYXJhdGUoY29sID0gImluZm8xIiwgaW50byA9IGMoImp1bmsiLCAiU3lzdGVtYXRpY19uYW1lIiksIHNlcCA9ICI6IikgJT4lCnNlcGFyYXRlKGNvbCA9ICJpbmZvMiIsIGludG8gPSBjKCJqdW5rMiIsICJHZW5lIiksIHNlcCA9ICJOYW1lPSIpICU+JQpzZXBhcmF0ZShjb2wgPSAiaW5mbzMiLCBpbnRvID0gYygianVuazMiLCAiRGVzY3JpcHRpb24xIiksIHNlcCA9ICJkZXNjcmlwdGlvbj0iKSAlPiUgIApzZXBhcmF0ZShjb2wgPSAiaW5mbzQiLCBpbnRvID0gYygianVuazQiLCAiRGVzY3JpcHRpb24yIiksIHNlcCA9ICJkZXNjcmlwdGlvbj0iKSAlPiUKc2VsZWN0KGMoRGVzY3JpcHRpb24xLCBEZXNjcmlwdGlvbjIpKQpgYGAKCiMjIENvbWJpbmUgY29sdW1ucyB3aXRoIGB1bml0ZSgpYCB7LnNtYWxsZXJ9CmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpnZmYgJT4lCm11dGF0ZShsZW5ndGggPSBhYnMoc3RhcnQgLSBzdG9wKSkgJT4lCmZpbHRlcihmZWF0dXJlID09ICJnZW5lIikgJT4lCnNlcGFyYXRlKGNvbCA9ICJpbmZvIiwgaW50byA9IGMoImluZm8xIiwgImluZm8yIiwgImluZm8zIiwgImluZm80IiwgImluZm81IiksIHNlcCA9ICI7IiwgZXh0cmEgPSAibWVyZ2UiKSAlPiUKc2VwYXJhdGUoY29sID0gImluZm8xIiwgaW50byA9IGMoImp1bmsiLCAiU3lzdGVtYXRpY19uYW1lIiksIHNlcCA9ICI6IikgJT4lCnNlcGFyYXRlKGNvbCA9ICJpbmZvMiIsIGludG8gPSBjKCJqdW5rMiIsICJHZW5lIiksIHNlcCA9ICJOYW1lPSIpICU+JQpzZXBhcmF0ZShjb2wgPSAiaW5mbzMiLCBpbnRvID0gYygianVuazMiLCAiRGVzY3JpcHRpb24xIiksIHNlcCA9ICJkZXNjcmlwdGlvbj0iKSAlPiUgIApzZXBhcmF0ZShjb2wgPSAiaW5mbzQiLCBpbnRvID0gYygianVuazQiLCAiRGVzY3JpcHRpb24yIiksIHNlcCA9ICJkZXNjcmlwdGlvbj0iKSAlPiUgICAgCnVuaXRlKERlc2NyaXB0aW9uLCBEZXNjcmlwdGlvbjEsIERlc2NyaXB0aW9uMiwgc2VwID0gIjoiKSAlPiUKc2VsZWN0KGMoRGVzY3JpcHRpb24pKQpgYGAKCiMjIFNhdmUgdG8gYSBuZXcgdmFyaWFibGUgey5zbWFsbGVyfQpBIGdlbmVyYWwgcnVsZSBpcyBpZiB5b3UgYXJlIHBpcGluZyBtb3JlIHRoYW4gMTAgc3RlcHMgc2F2ZSBhcyBhIG5ldyB2YXJpYWJsZQpgYGB7ciwgd2FybmluZz1GQUxTRX0KZ2ZmX2NsZWFuIDwtIGdmZiAlPiUKbXV0YXRlKGxlbmd0aCA9IGFicyhzdGFydCAtIHN0b3ApKSAlPiUKZmlsdGVyKGZlYXR1cmUgPT0gImdlbmUiKSAlPiUKc2VwYXJhdGUoY29sID0gImluZm8iLCBpbnRvID0gYygiaW5mbzEiLCAiaW5mbzIiLCAiaW5mbzMiLCAiaW5mbzQiLCAiaW5mbzUiKSwgc2VwID0gIjsiLCBleHRyYSA9ICJtZXJnZSIpICU+JQpzZXBhcmF0ZShjb2wgPSAiaW5mbzEiLCBpbnRvID0gYygianVuayIsICJTeXN0ZW1hdGljX25hbWUiKSwgc2VwID0gIjoiKSAlPiUKc2VwYXJhdGUoY29sID0gImluZm8yIiwgaW50byA9IGMoImp1bmsyIiwgIkdlbmUiKSwgc2VwID0gIk5hbWU9IikgJT4lCnNlcGFyYXRlKGNvbCA9ICJpbmZvMyIsIGludG8gPSBjKCJqdW5rMyIsICJEZXNjcmlwdGlvbjEiKSwgc2VwID0gImRlc2NyaXB0aW9uPSIpICU+JSAgCnNlcGFyYXRlKGNvbCA9ICJpbmZvNCIsIGludG8gPSBjKCJqdW5rNCIsICJEZXNjcmlwdGlvbjIiKSwgc2VwID0gImRlc2NyaXB0aW9uPSIpICU+JSAgICAKdW5pdGUoRGVzY3JpcHRpb24sIERlc2NyaXB0aW9uMSwgRGVzY3JpcHRpb24yLCBzZXAgPSAiIikgJT4lCnNlbGVjdChjKFN5c3RlbWF0aWNfbmFtZSwgR2VuZSwgRGVzY3JpcHRpb24pKQpgYGAKCiMjIENsZWFuIHVwIHN0cmluZ3Mgd2l0aCBgc3RyaW5ncigpYCB7LnNtYWxsZXJ9CmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpnZmZfY2xlYW4kRGVzY3JpcHRpb24gPC0gc3RyX3JlcGxhY2VfYWxsKGdmZl9jbGVhbiREZXNjcmlwdGlvbiwgIiUzQiIsICIiKQpnZmZfY2xlYW4kRGVzY3JpcHRpb24gPC0gc3RyX3JlcGxhY2VfYWxsKGdmZl9jbGVhbiREZXNjcmlwdGlvbiwgIiUyQyIsICIiKQpnZmZfY2xlYW4kRGVzY3JpcHRpb24gPC0gc3RyX3JlcGxhY2VfYWxsKGdmZl9jbGVhbiREZXNjcmlwdGlvbiwgIl5OQSIsICIiKQoKZ2ZmX2NsZWFuICU+JQpzZWxlY3QoYyhEZXNjcmlwdGlvbikpCgpgYGAKCiMjIFdyaXRlIGZpbGUKYGBge3J9CndyaXRlX3RzdihnZmZfY2xlYW4sICJZZWFzdF9nZW5lcy50eHQiLCBuYSA9ICJOQSIpCmBgYAoKCiMjIEhvdyBkbyB3ZSBjb21iaW5lIHRhYmxlcz8KCiMjIyBNdXRhdGluZyBqb2lucwpBIG11dGF0aW5nIGpvaW4gYWxsb3dzIHlvdSBjb21iaW5lIHZhcmlhYmxlcyBmcm9tIHR3byB0YWJsZXMgYnkgbWF0Y2hpdW5nIG9ic2VydmF0aW9ucyBieSB0aGVpciBrZXlzCgojIyMjIDEuIElubmVyIEpvaW4KbWF0Y2hlcyBwYWlycyBvZiBvYnNlcnZhdGlvbiBmcm9tIHR3byB0YWJsZXMgd2hlbmV2ZXIgdGhlaXIga2V5cyBhcmUgZXF1YWwKCiMjIyMgMi4gT3V0ZXIgam9pbgprZWVwcyBvYnNlcnZhdGlvbnMgdGhhdCBhcHBlYXIgaW4gYXQgbGVhc3Qgb25lIG9mIHRoZSB0YWJsZXMKCisgbGVmdCBqb2luIGtlZXBzIGFsbCB0aGUgb2JzZXJ2YXRpb25zIGluIHggKHNob3VsZCBiZSB0aGUgZGVmYXVsdCkKKyByaWdodCBqb2luIGtlZXBzIGFsbCB0aGUgb2JzZXJ2YXRpb25zIGluIHkKKyBmdWxsIGpvaW4ga2VlcHMgYWxsIG9ic2VydmF0aW9ucyBpbiB4IGFuZCB5CgojIyMgMy4gRmlsdGVyaW5nIGpvaW5zCmFmZmVjdHMgKGZpbHRlcnMpIHRoZSBvYnNlcnZhdGlvbnMgbm90IHRoZSB2YXJpYWJsZXMKCisgc2VtaV9qb2luKHgsIHkpIGtlZXBzIGFsbCBvYnNlcnZhdGlvbnMgaW4geCB0aGF0IGhhdmUgYSBtYXRjaCBpbiB5CisgYW50aV9qb2luKHgsIHkpIGRyb3BzIGFsbCBvYnNlcnZhdGlvbnMgaW4geCB0aGF0IGhhdmUgYSBtYXRjaCBpbiB5CgojIyBEYXRhc2V0IG11c3QgY29udGFpbiBjb21tb24gdmFsdWVzIChnZW5lIG5hbWVzKSB7LnNtYWxsZXJ9CmBgYHtyIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmRhdGEgPC0gIHJlYWRfZGVsaW0oIk5leW1vdGluX1RhYmxlX1MxLnR4dCIsIAogICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBUUlVFLCAKICAgIGNvbW1lbnQgPSAiIyIsIHRyaW1fd3MgPSBUUlVFKQpgYGAKCmBgYHtyfQpzdHIoZGF0YSkKYGBgCgojIyBGaWxlIHRvIGpvaW4gd2l0aApgYGB7cn0Kc3RyKGdmZl9jbGVhbikKYGBgCgojIyBKb2luaW5nIGRhdGEKYGRwbHlyOjpsZWZ0X2pvaW4oYSwgYiwgYnkgPSAieDEiKWAKSm9pbiBtYXRjaGluZyByb3dzIGZyb20gYiB0byBhLgoKYGBge3J9CmxlZnRfam9pbihnZmZfY2xlYW4sIGRhdGEsIGJ5ID0gYygiU3lzdGVtYXRpY19uYW1lIiA9ICJTeXN0IikpICU+JQogICAgICAgIHN0cigpCmBgYAoKIyMgRXhlcmNpc2UgNAoKdGlkeSBkYXRhIGRvbid0IGFsbG93IGVhc3kgY29ycmVsYXRpb24gcGxvdHMsIHNvIHdlIG5lZWQgdG8gcmVhcnJhZ2UgdGhlIGRhdGEKCmBgYHtyfQp0aWR5X2dlbmVfZXhwcmVzc2lvbiA8LSBnZW5lX2V4cHJlc3Npb24gJT4lCiAgICAgICAgZ2F0aGVyKHQwOnQyLCBrZXkgPSAidGltZXBvaW50IiwgdmFsdWUgPSAiZXhwcmVzc2lvbiIpCnRpZHlfZ2VuZV9leHByZXNzaW9uCmBgYAoKIyMgUmVhcnJhbmdlIHRoZSBkYXRhIAoKYGBge3IgZWNobz1GQUxTRX0KdGlkeV9nZW5lX2V4cHJlc3Npb24gJT4lCiAgICAgICAgc3ByZWFkKGtleSA9IHRpbWVwb2ludCwgdmFsdWUgPSBleHByZXNzaW9uKQpgYGAKCiMjIFBsb3QgY29ycmVsYXRpb24gYmV0d2VlbiB0MCBhbmQgdDEKCmBgYHtyIGVjaG89RkFMU0V9CnRpZHlfZ2VuZV9leHByZXNzaW9uICU+JQogICAgICAgIHNwcmVhZChrZXkgPSB0aW1lcG9pbnQsIHZhbHVlID0gZXhwcmVzc2lvbikgJT4lCiAgICAgICAgZ2dwbG90KGFlcyh4ID0gdDAsIHkgPSB0MSkpICsgCiAgICAgICAgZ2VvbV9wb2ludCgpCmBgYAoKIyMgRXhlcmNpc2UgNQoKKyBHZXQgdGhlIGdmZiBmaWxlIGZvciB5b3VyIGZhdm9yaXRlIG9yZ2FuaXNtCisgVGlkeSB0aGUgZ2ZmCisgcGxvdCBkaXN0cmlidXRpb24gb2YgZmVhdHVyZXMgcGVyIGNocm9tb3NvbWUKCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpnZmYgPC0gcmVhZF9kZWxpbSgiU2FjY2hhcm9teWNlc19jZXJldmlzaWFlLlI2NC0xLTEuMzQuZ2ZmMyIsIAogICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBGQUxTRSwgCiAgICBjb21tZW50ID0gIiMiLCB0cmltX3dzID0gVFJVRSwgc2tpcCA9IDI0KQpuYW1lcyhnZmYpIDwtIGMoImNocm9tb3NvbWUiLCAKICAgICAgICAgICAgICAgICJzb3VyY2UiLCAKICAgICAgICAgICAgICAgICJmZWF0dXJlIiwgCiAgICAgICAgICAgICAgICAic3RhcnQiLAogICAgICAgICAgICAgICAgInN0b3AiLCAKICAgICAgICAgICAgICAgICJ1bmtub3duMSIsCiAgICAgICAgICAgICAgICAic3RyYW5kIiwKICAgICAgICAgICAgICAgICJ1bmtub3duMiIsCiAgICAgICAgICAgICAgICAiaW5mbyIKICAgICAgICAgICAgICAgICkKI2NvcnJlY3QgZGF0YSB0eXBlcwpnZmYkZmVhdHVyZSA9IGFzLmZhY3RvcihnZmYkZmVhdHVyZSkKZ2ZmJGNocm9tb3NvbWUgPSBhcy5mYWN0b3IoZ2ZmJGNocm9tb3NvbWUpCmdmZiRzdHJhbmQgPSBhcy5mYWN0b3IoZ2ZmJHN0cmFuZCkKCnllYXN0X2ZlYXR1cmVzIDwtIGdmZiAlPiUKICAgICAgICBzZWxlY3QoY2hyb21vc29tZSwgZmVhdHVyZSwgc3RhcnQsIHN0b3AsIHN0cmFuZCkgJT4lCiAgICAgICAgbXV0YXRlKGxlbmd0aCA9IGFicyhzdGFydCAtIHN0b3ApKSAlPiUKICAgICAgICBmaWx0ZXIoZmVhdHVyZSA9PSAiQ0RTIiB8IGZlYXR1cmUgPT0gInJSTkEiIHwgZmVhdHVyZSA9PSAic25vUk5BIiB8IGZlYXR1cmUgPT0gInNuUk5BIiB8IGZlYXR1cmUgPT0gInRSTkFfZ2VuZSIpCmBgYAoKIyMgRXhhbXBsZQoKYGBge3IsIGZpZy53aWR0aD02LCBmaWcuYXNwID0gMC42MTgsIG91dC53aWR0aCA9ICI3MCUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0KZ2dwbG90KGRhdGEgPSB5ZWFzdF9mZWF0dXJlcywgbWFwcGluZyA9IGFlcyh4ID0gY2hyb21vc29tZSwgZmlsbCA9IGZlYXR1cmUpKSArCiAgICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKQpgYGAKCgoKIyMgUmVzb3VyY2VzCgoqIEJhc2UgUiB0byB0aWR5dmVyc2UgIGh0dHA6Ly93d3cuc2lnbmlmaWNhbnRkaWdpdHMub3JnLzIwMTcvMTAvc3dpdGNoaW5nLWZyb20tYmFzZS1yLXRvLXRpZHl2ZXJzZS8KKiBDaGVhdHNoZWV0OiBodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMi9kYXRhLXdyYW5nbGluZy1jaGVhdHNoZWV0LnBkZgoK