This notebook describes a data analysis pipeline for Andy Raptis - a
student who is working with Magda Julkowska at the remote internship, to
describe the color characteristics of flowers.
Load data:
First - let’s load a set of data that Andy has collected during his
internship:
list.files(pattern = ".csv")
[1] "Misc.1.csv" "Misc.2InsidePetal.csv" "Misc.2OutsidePetal.csv" "Misc.3.csv"
[5] "Misc.4.csv" "Misc.5.csv" "Misc.6.csv" "Sunflower.3.csv"
[9] "Sunflower.4.csv" "Sunflower.5.csv" "Sunflower.6.csv" "Sunflower.Control.csv"
[13] "Sunflower.InsidePetal.csv" "Sunflower.OutsidePetal.csv" "Sunflower.Petal.csv"
Sunflower1 <- read.csv("Sunflower.Control.csv")
Sunflower2 <- read.csv("Sunflower.3.csv")
Sunflower1
Sunflower2
Let’s remove all of the empty columns:
Sunflower1 <- Sunflower1[,1:4]
Sunflower2 <- Sunflower2[,1:4]
Sunflower1
Sunflower2
OK - now let’s remove empty rows with NAs:
Sunflower1 <- na.omit(Sunflower1)
Sunflower2 <- na.omit(Sunflower2)
Sunflower1
Sunflower2
Awesome - 1st column is actually called “Pixel value” and I would
like to rename it as such:
colnames(Sunflower1)[1] <- "Pix.values"
colnames(Sunflower2)[1] <- "Pix.values"
Sunflower1
Sunflower2
OK - so now what I would like to do is compare the distribution of
pixel values of two sunflowers - to do that - I would need to merge the
frames.
To be able to distinguish them - I have to add another collumn called
“sample ID”:
Sunflower1$SampleID <- "Sunflower01"
Sunflower2$SampleID <- "Sunflower03"
Sunflower1
Sunflower2
OK - now let’s merge the two data sets together:
library(reshape2)
Sunflower <- rbind(Sunflower1, Sunflower2)
Sunflower
to make sure we have two data sets correctly merged - I will check if
my unique SampleIDs in merged data frame are indeed what I expect:
unique(Sunflower$SampleID)
[1] "Sunflower01" "Sunflower03"
OK - looks good - moving on to plotting:
library(ggpubr)
Loading required package: ggplot2
library(ggsci)
library(ggplot2)
Red <- ggplot(data = Sunflower, aes(x = Pix.values, y = Red, colour = SampleID, group = SampleID))
Red <- Red + geom_line(alpha = 0.5) + scale_color_aaas()
Red

Now - let’s compare another color dimension:
Green <- ggplot(data = Sunflower, aes(x = Pix.values, y = Green, colour = SampleID, group = SampleID))
Green <- Green + geom_line(alpha = 0.5) + scale_color_aaas()
Green

Blue <- ggplot(data = Sunflower, aes(x = Pix.values, y = Blue, colour = SampleID, group = SampleID))
Blue <- Blue + geom_line(alpha = 0.5) + scale_color_aaas()
Blue

OK - this all looks good. And we can even plot all of these into one
graph, but before we need to melt the dataset:
SunM <- melt(Sunflower, id = c("SampleID", "Pix.values"))
SunM
RGB_plot <- ggplot(data = SunM, aes(x = Pix.values, y = value, colour = SampleID, group = SampleID))
RGB_plot <- RGB_plot + geom_line(alpha = 0.5)
RGB_plot <- RGB_plot + scale_color_aaas()
RGB_plot <- RGB_plot + facet_grid(~ variable)
RGB_plot

Now - we can see what channel gives us most difference between the
two samples we would like to compare. However - where are the
differences statistically significant?
In order to calculate this - we would have to change the values in
our tables to actual data.
How the table looks like for each RGB variable - it represents the %
of pixels.
What we need is to have the data of points that will have that
specific value. Let’s do an example here below:
SunM
So I dont want to have any of the pixels that have value of 0 - so
let’s remove them:
SunPix <- subset(SunM, SunM$value > 0)
SunPix
Then - I would like to have 134 pixels that is having value of 140 in
Red, same for 145 and so on…. but how do I do it?
Maybe let’s first multiply everything by a thousand so we have only
the WHOLE observations:
SunPix$obs <- SunPix$value * 1000
SunPix
OK - now we need to re-calculate all of this into individual
observations. Let’s start with the first one to begin with:
temp <- SunPix[1,1:3]
temp
reps <- as.numeric(SunPix$obs[1])
temp2 <- do.call("rbind", replicate(reps, temp, simplify = FALSE))
SunCount <- temp2
SunCount
cool - now let’s loop it for all of the rows in the SunPix
dataframe:
for(i in 2:nrow(SunPix)){
temp <- SunPix[i,1:3]
temp
reps <- as.numeric(SunPix$obs[i])
temp2 <- do.call("rbind", replicate(reps, temp, simplify = FALSE))
SunCount <- rbind(SunCount, temp2)
}
head(SunCount)
dim(SunCount)
[1] 599962 3
OK - now that we have our data in correct format, let’s plot it
again, but using slighltly different methods:
library(ggsci)
library(ggpubr)
color_plot <- ggviolin(SunCount, x = "SampleID", y = "Pix.values", color = "SampleID", fill = "SampleID",
facet.by = "variable",
desc_stat = "mean_sd", add = "boxplot", add.params = list(fill = "white"),
xlab="", ylab= "number of pixels")
color_plot <- color_plot + stat_compare_means(aes(label = after_stat(p.signif)), method = "aov", hide.ns = F)
color_plot <- color_plot + rremove("legend") + scale_color_d3("category10") + scale_fill_d3("category10")
color_plot <- color_plot + theme(axis.text.x = element_text(angle = 90))
color_plot

LS0tCnRpdGxlOiAiQW5keSBDb2xvciBkaXN0cmlidXRpb24iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgbm90ZWJvb2sgZGVzY3JpYmVzIGEgZGF0YSBhbmFseXNpcyBwaXBlbGluZSBmb3IgQW5keSBSYXB0aXMgLSBhIHN0dWRlbnQgd2hvIGlzIHdvcmtpbmcgd2l0aCBNYWdkYSBKdWxrb3dza2EgYXQgdGhlIHJlbW90ZSBpbnRlcm5zaGlwLCB0byBkZXNjcmliZSB0aGUgY29sb3IgY2hhcmFjdGVyaXN0aWNzIG9mIGZsb3dlcnMuIAoKIyBMb2FkIGRhdGE6CgpGaXJzdCAtIGxldCdzIGxvYWQgYSBzZXQgb2YgZGF0YSB0aGF0IEFuZHkgaGFzIGNvbGxlY3RlZCBkdXJpbmcgaGlzIGludGVybnNoaXA6CgpgYGB7cn0KbGlzdC5maWxlcyhwYXR0ZXJuID0gIi5jc3YiKQoKU3VuZmxvd2VyMSA8LSByZWFkLmNzdigiU3VuZmxvd2VyLkNvbnRyb2wuY3N2IikKU3VuZmxvd2VyMiA8LSByZWFkLmNzdigiU3VuZmxvd2VyLjMuY3N2IikKU3VuZmxvd2VyMQpTdW5mbG93ZXIyCmBgYApMZXQncyByZW1vdmUgYWxsIG9mIHRoZSBlbXB0eSBjb2x1bW5zOgoKYGBge3J9ClN1bmZsb3dlcjEgPC0gU3VuZmxvd2VyMVssMTo0XQpTdW5mbG93ZXIyIDwtIFN1bmZsb3dlcjJbLDE6NF0KU3VuZmxvd2VyMQpTdW5mbG93ZXIyCmBgYAoKT0sgLSBub3cgbGV0J3MgcmVtb3ZlIGVtcHR5IHJvd3Mgd2l0aCBOQXM6CgpgYGB7cn0KU3VuZmxvd2VyMSA8LSBuYS5vbWl0KFN1bmZsb3dlcjEpClN1bmZsb3dlcjIgPC0gbmEub21pdChTdW5mbG93ZXIyKQpTdW5mbG93ZXIxClN1bmZsb3dlcjIKYGBgCgpBd2Vzb21lIC0gMXN0IGNvbHVtbiBpcyBhY3R1YWxseSBjYWxsZWQgIlBpeGVsIHZhbHVlIiBhbmQgSSB3b3VsZCBsaWtlIHRvIHJlbmFtZSBpdCBhcyBzdWNoOgoKYGBge3J9CmNvbG5hbWVzKFN1bmZsb3dlcjEpWzFdIDwtICJQaXgudmFsdWVzIgpjb2xuYW1lcyhTdW5mbG93ZXIyKVsxXSA8LSAiUGl4LnZhbHVlcyIKU3VuZmxvd2VyMQpTdW5mbG93ZXIyCmBgYApPSyAtIHNvIG5vdyB3aGF0IEkgd291bGQgbGlrZSB0byBkbyBpcyBjb21wYXJlIHRoZSBkaXN0cmlidXRpb24gb2YgcGl4ZWwgdmFsdWVzIG9mIHR3byBzdW5mbG93ZXJzIC0gdG8gZG8gdGhhdCAtIEkgd291bGQgbmVlZCB0byBtZXJnZSB0aGUgZnJhbWVzLiAKClRvIGJlIGFibGUgdG8gZGlzdGluZ3Vpc2ggdGhlbSAtIEkgaGF2ZSB0byBhZGQgYW5vdGhlciBjb2xsdW1uIGNhbGxlZCAic2FtcGxlIElEIjoKCmBgYHtyfQpTdW5mbG93ZXIxJFNhbXBsZUlEIDwtICJTdW5mbG93ZXIwMSIKU3VuZmxvd2VyMiRTYW1wbGVJRCA8LSAiU3VuZmxvd2VyMDMiClN1bmZsb3dlcjEKU3VuZmxvd2VyMgpgYGAKT0sgLSBub3cgbGV0J3MgbWVyZ2UgdGhlIHR3byBkYXRhIHNldHMgdG9nZXRoZXI6CgpgYGB7cn0KbGlicmFyeShyZXNoYXBlMikKU3VuZmxvd2VyIDwtIHJiaW5kKFN1bmZsb3dlcjEsIFN1bmZsb3dlcjIpClN1bmZsb3dlcgpgYGAKdG8gbWFrZSBzdXJlIHdlIGhhdmUgdHdvIGRhdGEgc2V0cyBjb3JyZWN0bHkgbWVyZ2VkIC0gSSB3aWxsIGNoZWNrIGlmIG15IHVuaXF1ZSBTYW1wbGVJRHMgaW4gbWVyZ2VkIGRhdGEgZnJhbWUgYXJlIGluZGVlZCB3aGF0IEkgZXhwZWN0OgoKYGBge3J9CnVuaXF1ZShTdW5mbG93ZXIkU2FtcGxlSUQpCmBgYAoKT0sgLSBsb29rcyBnb29kIC0gbW92aW5nIG9uIHRvIHBsb3R0aW5nOgoKYGBge3J9CmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGdnc2NpKQpsaWJyYXJ5KGdncGxvdDIpCgpSZWQgPC0gZ2dwbG90KGRhdGEgPSBTdW5mbG93ZXIsIGFlcyh4ID0gUGl4LnZhbHVlcywgeSA9IFJlZCwgY29sb3VyID0gU2FtcGxlSUQsIGdyb3VwID0gU2FtcGxlSUQpKSAKUmVkIDwtIFJlZCArIGdlb21fbGluZShhbHBoYSA9IDAuNSkgKyBzY2FsZV9jb2xvcl9hYWFzKCkgClJlZApgYGAKTm93IC0gbGV0J3MgY29tcGFyZSBhbm90aGVyIGNvbG9yIGRpbWVuc2lvbjoKCmBgYHtyfQpHcmVlbiA8LSBnZ3Bsb3QoZGF0YSA9IFN1bmZsb3dlciwgYWVzKHggPSBQaXgudmFsdWVzLCB5ID0gR3JlZW4sIGNvbG91ciA9IFNhbXBsZUlELCBncm91cCA9IFNhbXBsZUlEKSkgCkdyZWVuIDwtIEdyZWVuICsgZ2VvbV9saW5lKGFscGhhID0gMC41KSArIHNjYWxlX2NvbG9yX2FhYXMoKSAKR3JlZW4KYGBgCgpgYGB7cn0KQmx1ZSA8LSBnZ3Bsb3QoZGF0YSA9IFN1bmZsb3dlciwgYWVzKHggPSBQaXgudmFsdWVzLCB5ID0gQmx1ZSwgY29sb3VyID0gU2FtcGxlSUQsIGdyb3VwID0gU2FtcGxlSUQpKSAKQmx1ZSA8LSBCbHVlICsgZ2VvbV9saW5lKGFscGhhID0gMC41KSArIHNjYWxlX2NvbG9yX2FhYXMoKSAKQmx1ZQpgYGAKT0sgLSB0aGlzIGFsbCBsb29rcyBnb29kLiBBbmQgd2UgY2FuIGV2ZW4gcGxvdCBhbGwgb2YgdGhlc2UgaW50byBvbmUgZ3JhcGgsIGJ1dCBiZWZvcmUgd2UgbmVlZCB0byBtZWx0IHRoZSBkYXRhc2V0OgoKYGBge3J9ClN1bk0gPC0gbWVsdChTdW5mbG93ZXIsIGlkID0gYygiU2FtcGxlSUQiLCAiUGl4LnZhbHVlcyIpKQpTdW5NCmBgYAoKYGBge3J9ClJHQl9wbG90IDwtIGdncGxvdChkYXRhID0gU3VuTSwgYWVzKHggPSBQaXgudmFsdWVzLCB5ID0gdmFsdWUsIGNvbG91ciA9IFNhbXBsZUlELCBncm91cCA9IFNhbXBsZUlEKSkgClJHQl9wbG90IDwtIFJHQl9wbG90ICsgZ2VvbV9saW5lKGFscGhhID0gMC41KSAKUkdCX3Bsb3QgPC0gUkdCX3Bsb3QgKyBzY2FsZV9jb2xvcl9hYWFzKCkgClJHQl9wbG90IDwtIFJHQl9wbG90ICsgZmFjZXRfZ3JpZCh+IHZhcmlhYmxlKQpSR0JfcGxvdApgYGAKTm93IC0gd2UgY2FuIHNlZSB3aGF0IGNoYW5uZWwgZ2l2ZXMgdXMgbW9zdCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBzYW1wbGVzIHdlIHdvdWxkIGxpa2UgdG8gY29tcGFyZS4gSG93ZXZlciAtIHdoZXJlIGFyZSB0aGUgZGlmZmVyZW5jZXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudD8gCgpJbiBvcmRlciB0byBjYWxjdWxhdGUgdGhpcyAtIHdlIHdvdWxkIGhhdmUgdG8gY2hhbmdlIHRoZSB2YWx1ZXMgaW4gb3VyIHRhYmxlcyB0byBhY3R1YWwgZGF0YS4KCkhvdyB0aGUgdGFibGUgbG9va3MgbGlrZSBmb3IgZWFjaCBSR0IgdmFyaWFibGUgLSBpdCByZXByZXNlbnRzIHRoZSAlIG9mIHBpeGVscy4gCgpXaGF0IHdlIG5lZWQgaXMgdG8gaGF2ZSB0aGUgZGF0YSBvZiBwb2ludHMgdGhhdCB3aWxsIGhhdmUgdGhhdCBzcGVjaWZpYyB2YWx1ZS4gTGV0J3MgZG8gYW4gZXhhbXBsZSBoZXJlIGJlbG93OgoKYGBge3J9ClN1bk0KYGBgCgpTbyBJIGRvbnQgd2FudCB0byBoYXZlIGFueSBvZiB0aGUgcGl4ZWxzIHRoYXQgaGF2ZSB2YWx1ZSBvZiAwIC0gc28gbGV0J3MgcmVtb3ZlIHRoZW06CgpgYGB7cn0KU3VuUGl4IDwtIHN1YnNldChTdW5NLCBTdW5NJHZhbHVlID4gMCkKU3VuUGl4CmBgYAoKVGhlbiAtIEkgd291bGQgbGlrZSB0byBoYXZlIDEzNCBwaXhlbHMgdGhhdCBpcyBoYXZpbmcgdmFsdWUgb2YgMTQwIGluIFJlZCwgc2FtZSBmb3IgMTQ1IGFuZCBzbyBvbi4uLi4gYnV0IGhvdyBkbyBJIGRvIGl0PwoKTWF5YmUgbGV0J3MgZmlyc3QgbXVsdGlwbHkgZXZlcnl0aGluZyBieSBhIHRob3VzYW5kIHNvIHdlIGhhdmUgb25seSB0aGUgV0hPTEUgb2JzZXJ2YXRpb25zOgoKYGBge3J9ClN1blBpeCRvYnMgPC0gU3VuUGl4JHZhbHVlICogMTAwMApTdW5QaXgKYGBgCk9LIC0gbm93IHdlIG5lZWQgdG8gcmUtY2FsY3VsYXRlIGFsbCBvZiB0aGlzIGludG8gaW5kaXZpZHVhbCBvYnNlcnZhdGlvbnMuIExldCdzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IG9uZSB0byBiZWdpbiB3aXRoOgoKYGBge3J9CnRlbXAgPC0gU3VuUGl4WzEsMTozXQp0ZW1wCnJlcHMgPC0gYXMubnVtZXJpYyhTdW5QaXgkb2JzWzFdKQp0ZW1wMiA8LSBkby5jYWxsKCJyYmluZCIsIHJlcGxpY2F0ZShyZXBzLCB0ZW1wLCBzaW1wbGlmeSA9IEZBTFNFKSkKU3VuQ291bnQgPC0gdGVtcDIKU3VuQ291bnQKYGBgCgpjb29sIC0gbm93IGxldCdzIGxvb3AgaXQgZm9yIGFsbCBvZiB0aGUgcm93cyBpbiB0aGUgU3VuUGl4IGRhdGFmcmFtZToKCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFLCBwYWdlZC5wcmludD1UUlVFfQpmb3IoaSBpbiAyOm5yb3coU3VuUGl4KSl7CiAgdGVtcCA8LSBTdW5QaXhbaSwxOjNdCiAgcmVwcyA8LSBhcy5udW1lcmljKFN1blBpeCRvYnNbaV0pCiAgdGVtcDIgPC0gZG8uY2FsbCgicmJpbmQiLCByZXBsaWNhdGUocmVwcywgdGVtcCwgc2ltcGxpZnkgPSBGQUxTRSkpCiAgU3VuQ291bnQgPC0gcmJpbmQoU3VuQ291bnQsIHRlbXAyKQp9CmBgYAoKCmBgYHtyfQpoZWFkKFN1bkNvdW50KQpkaW0oU3VuQ291bnQpCmBgYApPSyAtIG5vdyB0aGF0IHdlIGhhdmUgb3VyIGRhdGEgaW4gY29ycmVjdCBmb3JtYXQsIGxldCdzIHBsb3QgaXQgYWdhaW4sIGJ1dCB1c2luZyBzbGlnaGx0bHkgZGlmZmVyZW50IG1ldGhvZHM6CgpgYGB7cn0KbGlicmFyeShnZ3NjaSkKbGlicmFyeShnZ3B1YnIpCgpjb2xvcl9wbG90IDwtIGdndmlvbGluKFN1bkNvdW50LCB4ID0gIlNhbXBsZUlEIiwgeSA9ICJQaXgudmFsdWVzIiwgY29sb3IgPSAiU2FtcGxlSUQiLCBmaWxsID0gIlNhbXBsZUlEIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZXQuYnkgPSAidmFyaWFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2Nfc3RhdCA9ICJtZWFuX3NkIiwgYWRkID0gImJveHBsb3QiLCBhZGQucGFyYW1zID0gbGlzdChmaWxsID0gIndoaXRlIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgeGxhYj0iIiwgeWxhYj0gIm51bWJlciBvZiBwaXhlbHMiKQpjb2xvcl9wbG90IDwtIGNvbG9yX3Bsb3QgKyBzdGF0X2NvbXBhcmVfbWVhbnMoYWVzKGxhYmVsID0gYWZ0ZXJfc3RhdChwLnNpZ25pZikpLCBtZXRob2QgPSAiYW92IiwgaGlkZS5ucyA9IEYpCmNvbG9yX3Bsb3QgPC0gY29sb3JfcGxvdCArIHJyZW1vdmUoImxlZ2VuZCIpICsgc2NhbGVfY29sb3JfZDMoImNhdGVnb3J5MTAiKSArIHNjYWxlX2ZpbGxfZDMoImNhdGVnb3J5MTAiKQpjb2xvcl9wbG90IDwtIGNvbG9yX3Bsb3QgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKY29sb3JfcGxvdApgYGAKCgoK