Untitled

You might also like

You are on page 1of 20
= MENU Search and hit enter... Q. DAVE TANG’S BLOG COMPUTATIONAL BIOLOGY AND GENOMICS Animated plots using R DAVO FEBRUARY 12,2015 7 learned the simple concept of animation back in school, when some of my classmates would draw stick figures on the edge of large textbooks. At first | was wondering why one would defile a textbook in such a way, but then as they flipped through the pages and brought the stick figures to life, |was in awe. Despite this, at that stage of my life, a textbook was sacred to me (they were expensive and scarce), so | would use large Post-it notes to doodle instead. | wasn't very good at drawing (even when it comes to stick figures), so | made a few animations and that was it. This post is on creating animated plots using R. | wrote it not because | wanted to rekindle my youthful interest in stick figure animation but because | wanted to create an animated plot for an upcoming talk. | found a short post on creating animated plots using R and | follow the same idea of making multiple plots and then combining them into a GIF using ImageMagick. 1| #nunber of frames or plots 2| frames <- 50 5 4| # function for creating file name with leading zeros 5 | # makes it easier to process them sequentially 6 | rename <- function(x){ 7| iF (x < 30) ¢ 8 etura(nane <- paste('@e0",4, "plot.png',sep="*)) es] } 10} If (x ¢ 200 8& 1 >= 10) ( a return(name <- paste('0",4, "plot.png', sep="")) nl} } 23 | if (x >= 200) { 1a return(name <- paste('@", i,"plot.png’, sep= as} is} } uv 18| #loop through plots 19 | for(i in 1:frames)( 20) name <- renane(i) 2a 22| saves the plot as a .png file in the working directory 23 png(name) 24) sd<- 10 25| on <- 10000 26| factor <- i * 2 27| mm <- $8 + factor 28) x <- rnorm(n, m, sd) 29 | hist(x, xi (8,208), o (@, 2000) paste("Histogram of rnorm() n=", n, ‘mean =‘, m * 34 35 36 37 38 dev.off() trun ImageMagick ‘my_conmand <- ‘convert *.png -delay 3 -loop @ animation.gif* syStem(my_conmand) Histogram of rnorm()n = 10000 moan = 52 sd= 10 8 : 28 z 2 The distribution shifts according to the mean. Visualise filtering threshold A practical use of animated plots could be to visualise the effects of independent filtering on the number of genes detected as differentially expressed, frames <- 50 rename <- function(x){ if (x < 18) { rreturn(name <- paste(*9e0" 4, 'plot.png" sep » Lf (x ¢ 108 && i >= 10) ( return(name <= paste('6o",i, plot.png', sep='')) } IF (x >= 100) ( retura(name <- paste(*e", i, "plot.png', sep ? » y #I host this file on my server for convenience file_url <- ‘http://davetang.org/eg/pnas_expression.txt' data <- read.table(file_url, header=T, sep="\t", stringsAsFactors=F, row.nanes=1 ) 22 23| remove length column 24| data <- datal,-8] 25 26 | Library(edger) 27 28 | #loop through plots 29) for(i in 1:frames){ 30) name <- renane(4) 31 32 | saves the plot as a png file in the working directory 33 | png(name) 34) data_subset <- subset(data, rowSuns(data)>i) 35| group <- c(rep("Control",4), rep("Test",3)) 36) d <- DGEList(counts = data_subset, group=group) 37| data normalisation 38| d <- calcNormFactors(d, method="THM") 39| d <- estinateDisp(d) 40} et <- exactTest(d) 41| de <- table(p.adjust(et$tablegpvalue, method = "BH")<0.05)[2] 42 43| — plot(et$table$logcrm, 44 et$tableslogrc, 45 46 47 43 cex=0.1, 49 col=as.nuneric(p.adjust(et$table$pValue, method = "BH")<0.5)+1, 5@ main=paste("Independent filtering at", i, ';', de, ‘differentially expressed") 51 ) 52] _ dev.of () 53] } 54 55 | #run ImageMagick 56| aI slowed it down a bit more 57 | my_command <- ‘convert *.png -delay 5 -loop @ filtering. gif’ 58 | system(my_conmand) Independent filtering at 1 ; 4230 differentially expressed g g° o 2 4 6 8 7 061244 etStablesiogcPM ‘Adjusting the filtering threshold did not have a large effect on the number of differentially expressed genes. (This isn't always the"CGSe.) Rotating 3D scatter plot #install.packages(""scatterplot3d") Library (scatterplot3d) data(inis) frames <- 368 rename <- function(x){ if (x < 18) { return(name <- paste('ee0' ,, 'plot.png',sep="')) > Se (x ¢ 100 88 4 > 10) ¢ return(nane < paste('82",4,"plot.png', sep="")) ? Tf (x >= 108) ¢ return(name <- paste('@", i,"plot.png", sep="")) ? + p <- preomp(inis[,1:4]) my_col <- as.nuneric(inis$Species) #loop through plots for(i in 1:frames){ name <- rename(i) fisaves the plot as a .png file in the working directory png(name) Scatterplot3d(p$x[ 41:3], main=paste("Angle”, i), angle-i, pch=19, cex.symbols=@.5, color=ny_col) dev.of F() my_conmand <- ‘convert *.png -delay 1 -loop @ 3d.gif* sySten(my_conmand) Angle 1 Pea Visualising the three principal components using a 3D scatter plot. Stick figures 1] # the XKCD package has a nore flexible function for creating stick figures but perhaps for another « 2| # this draw.stick function is fron 3 | # netpst//eithu. con/EcononetricsBySinulat ion/R-Graphics/blob/naster/Stick-Figures/draw. stick.& 4| w stick Man/Wonan Generating Function 6 | draw.stick <- function(x,y, scale=1,arns="down", 7 gender="male",lwd=3, clcol="white", 8 face="happy", linecol=gray(.3), 9 hat=na) { 10] # cleol: color of clothes - any color ii} # scale: fize of figure 22] # x,y left bottom alignnent of figure 13| —# Linecol: color of lines - any color 14] # Iwd: line weight a5 16 * up", "hip", “wave™ vl) # 18 + "annoyed", “surprised” 19] # Hat: plot hat’ TF 20 21] 4 Set the Figure scale, default st 1 22 s <> scale/100 23 2a! TF 4s undefined then give the man 2 hat 25| if (isnahat)) hat«-(gender=="naie") 26 27 require("plotrix") 28 “| praw Head Graw.e1lipse(x+S0*s,y#75*s,10+s,15#s,1wd=lwd, border=1inecol) a if (faces="happy") { asf # Draw eyes, } Af (fac y if (face x if (fac y # Lines (c(x+50%S,x+50"5), c(y+35"s,y+60"5),lwd=lwd, co: # if (arms y Af (arms } Af (arms y if (arms Af (arms + # if (gender: } # if (gender!="mal draw. ellipse(x+46*s,y+77*s,2.5*s,2*s,lwd=lwd, border=linecol) draw.ellipse(x+5a*s,y+77*s, 2.5°5,2*S, Imi # Draw mouth draw.cllipse(x+50*s,y+72*s,6*s,8%S, segment Ind=lwd, border=Linecol) "sac") # brew eyes dranse1lepse(xtd6ts, y+75"S, 245, 245, Indelid, draw cellipse(xssaes,y-75"5, 2"8,2"8, Indeled, # Draw mouth draw.cllipse(x+50*s, y+60"s,6*s,8%s, segment Iwd=lwd, border=Linecol) urprised") { # Draw eyes draw.ellipse(x+46*s,y+78*s,3*s,2*s,Iwd=Iwd, draw.ellipse(xt54*s,y+78*S,3*s,2*S, lwd=Iwd, Draw irises # Draw mouth draw.ellipse(x+50*s,y+65*s,3*5,4*5, Iwd=1wd, border=Linecol) annoyed") { # Draw mouth Lines(c(x+46"s, 1554S), c(y#66*s,y+68"S),Iud=lud, col # Draw eyes draw. ellipse (xt46*s,y+76*s,24s,2*s,Iwd=lwd, dran.ellipse(xt+54*s,ys76"5,2*s,1*5, lwd=lwd, Draw torso Draw arms jown") { Lines (c(x#5@"s,x436*s),, Lines (e(xt50*5,x464*5), eutral") { Lines (c(x#50"s,x+30"s),, Lines (c(x#5@"s,x+70"s),, 11 CoerBet e324), Lines(c(xt50"s 0 68"5), ip") Lines (c(x#50%S, x+37*5,x448%5) , Lines (c(x+58*s, x+63*5,x451*5), wave") { Lines (c(x+50*s, 243845, x+33"S), Tines(c(x+50*s, 24635, x+52"S), Draw male legs male") { Lines (cQt50*s, x+40%s), c(y+35*s,y+5¢s), Im Lines (c(x+58*s,x+60%S), c(y+35"s,y+5*5) , LW Draw fenale legs and dress yt cy#55*5,y+30"S) , lMd=Ind, c(y#58*5,9+30%5) jId=lnd, c(y+50"s,y+55*s) , lwd=Lnd, c(y+50s,y+55*s) ,lwd=lnd, col cly#50"s,y+65%S), Iud=lud, col c(y#50*s,y+65*5) , lud=Lnd, (y#56%S, y447*s,y+40"s), IW (y+56*s, y449*s,y+62"s), Ind=lnd, (y+564S, y+60%s,y+78"5), Iw c(y+56"S, y447*s, ye40"s), Iwd=lwd, wd, border=linecol) = c(-160, -20), border=linecol) border=Tinecol) = (240,40), borders1inecol) border=linecol) draw.ellipse (x+46*s,y+78*s,1*s,1*s,1nd=lwd, border=linecol) draw.ellipse(x+54*s,y+78"s,1*s,1*s,1nd=lwd, border inecol) inecol) border=linecol) borderslinecol) ‘inecol) col-linecol) # Left inecol) # Right colslinecol) # Left inecol) # Right inecol) # Left col-linecol) # Right wd, col=linecol) # Left colslinecol) # Right wd, col=Linecol) # Left col=linecol) # Right wd, col=Linecol) wd, col=Linecol) 107 108 109 ne ua a2 13 ua us us. 7 us is 120 aa 422 23 124 as 126 127 128 129 130 131 132 33 B34 35 136 137 138 139 120 141 442 143 aaa 14s 146. 147 1s. 149 150 451 452 153, 154 155 156 157 158 159 160 161 162 163, 164 165 166 # Draw legs Lines (c(xta5*s,x+45%s), c(y#17"s,y+5*s),Iwd=lwd, col*linecol) Lines(c(x#55*s,x+55*5), c(y#17*s,y+5*s), Ind=Ind, col=linecol) # raw dress polygon(c(x+s*50,x45*35, x+s*65), c(y+s"40,y+s*17,y+s*17), col=cicol, border=Linecol, Ind=1Md) y # Draw hat if (hat==T) polygon( O435*S, X4654S, x+6545 ,x4594S, X45B"S, x+42*5,x4414, x435%5), (y#84¥S, y+B4"S, y+86"S ,y+B6"S, y491"S, y+91"S,y+B6*S, y+86"S), col=clcol, border=linecol, lwd=1wd) ? frames <- 50 rename <- function(x){ if (x < 18) ¢ return(name <- paste(*e00",i, ‘plot.png’,sep="')) } if (x < 100 8& i >= 10) { return(name <- paste(*80',i,'plot-png’, sep="')) Je ox >= 200) ¢ return(name <- paste(’e', 4,'plot.png', sep='')) y , loop through plots for(i in 1:frames){ nane <- rename(i) Hsaves the plot as a .png file in the working directory png(name) # Aems: "neutral", "up", "hip", “wave” # Gender: “Female” # 'sad", "annoyed", “surprised” # Hat: plot hat’ T,F a < c('down' ‘neutral’, ‘up", ‘hip’, ‘wave") < cChappy’, ‘sad’, ‘annoyed", ‘surprised’ ) h <- cCTRUE, FALSE) fs < sanple(f,1) as <- sanple(a,1) hs <- sampie(hy1) plot (c(.25,.75), 1) draw.Stick(®,®, face=fs, gender="nale", arms=as, hat=hs) dev.of F() ? trun ImageMagick my_conmand <- ‘convert *.png -delay 5 -loop @ stick figure. gif’ system(ny_command) happy wave TRUE os oO os 06 o7 0(0.25,0.75) The real motivation for this post. om This work is licensed under a Creative Commons Attribution 4.0 International License. i Posted in R, visualisation @ Tagged R, visualisation 7 COMMENTS BOB SETTLAGE February 12, 2015 at 1:11 pm Wow, great post. | too watched in horror as classmates defiled text books. | recently wanted to highlight assigned homework numbers in a text book. | considered how to do this for at least 10 min before making the slightest of dots next to the numbers. @ 5 Back to topic, | love the independent filtering gif. | might add to that a histogram showing number of deg at each filter value with the bar color changing/following as the value changes and a Venn showing overlap of degs between current and baseline (no filtering). REPLY DAVO February 12, 2015 at 1:14 pm Fastest comment Ive ever gotten ® And thanks for the great suggestion! REPLY MIKHAIL DOZMOROV April 6, 2015 at 2:12 pm Ittook me a while to find a way to overlay text on the 3D PCA plot. The package vignette, http://cran.r- projectorg/web/packages/scatterplot3d/vignettes/s3d.odf, shows how to do it on page 18. To make it work in Dave's example, simply use this code: Hloop through plots for(i in 1:frames name <- rename() #saves the plot asa png file in the working directory png(name) s3d < scatterplot3d(p$xl,1:31, angle=i, pch=19, cexsymbols=0.5, color=' col) +# Overlaying text s3d.coords < s3d$xyz.convert(p$x{1:3) text(s3d.coords$x, s3d.coordssy, labels-colnamestirisl, 1:4), pos=2, offset=0.5, ce) dev.off) y Obviously, it works best when the plot is not as crowded, ‘And, at the end of the example for the 3D PCA plot, I'd add a cleanup command system('rm *,png") nerty o Pingback: Miscellaneous plots in R - Musings from an unlikely candidateMusings from an unlikely candidate GRANT SCHULTZ April 10, 2018 at 9:19 pm With R 3.4.2 and ImageMagick 7.0.7-28 Q16 x64, you'll need the following call, instead of system() system2(‘magick’, (’convert’, “png lelay 3" Joop 0", “animation gif?) GREG July 25, 2018 at 12:16 am Thanks, Dave for a very cool set of animation examples. 1'm just getting started into that world & tried adapting you're example to iterate through a dataframe 1 row at a time to produce a basic line plot *unsuccessfully*, though. * AIl50 png files created include the plot of the entire data series ? Do | need to add a slept) cmd to the iterative plot generation? REPLY Davo Januory 23, 2019 at 9:09 am haven't had a chance to check out gganimate ( ps://github,corm/thomasp85/gganimate) but perhaps it might be easier to follow than my blog post. Leave a Reply Your email address will not be published, Required fields are marked * Comment Name * Email * Website ONiotify me of follow-up comments by email. O Notify me of new posts by email This site uses Akismet to reduce spam. Learn how your comment data is processed. Search ov Buy Me a Coffee WHO'S ONLINE 5 visitors online now 2 guests, 3 bots, 0 members “Visitors LIceN: xa This work is licensed under a Creative Commons Attribution 4.0 International License. RECENT Posts Backticks in R Wrapping R vectors with parentheses Split single column of key-value pairs into multiple cohimns Map, join, and pivot in R Mapping full-length mRNA sequences Finding out weather conditions from the command line Omicron variants Storing FASTQ as unaligned CRAM Updating my Docker documentation ENT COMMENTS Davo on Manual linear regression analysis using R Pablo G on Manual linear regression analysis using R Davo on Making a heatmap in R with the pheatmap package Eidunari on Making a heatmap in R with the pheatmap package Chris on Compiling R with GNU Readline Davo on Making a heatmap in R with the pheatmap package ‘Sanjana on Making a heat map in R with the pheatmap package Davo on Compiling R with GNU Readline Jas on Compiling R with GNU Readline Davo on Using Gviz TAG cLoua 10x ANNOLATION bam vectoots bioinformatics biomart CAGE Clustering correlation DGE docker encode etc ZENOME co graph heatmap histones machine learning MAPPiNg maths miRNA motif OMIM parser pca PEF oipeine promoter PR refseq repeats raseq SAM samtools SARS-CoV-2 sequencing spearman StatiStiCs symax ts TiS twitter variants Visualisation WITTER FEED Tweets from @davetang31 ty Dave Tang Retweeted 2 v @.. Oct 1 Ifyou use Wikipedia, you've seen pop-ups like this. If you're like me, you may have donated as a result. Wikipedia is an amazing website, and the appeals seem heartfelt. But I've now learnt the money isn’t going where | thought. © es © ask © ta Dave Tang Retweeted Kieran Dr... WF @lt.. Oct 1 Do you sit at a computer for longer than 6 hours a ani vody if so. Here's the setup you need to protect yourself from posture problems and crippling long-term injuries: x DK O 155K ® Dave Tang 8 Retweeted Heng Li vy @... Sep 28 Motivated by my earlier tweet and the responses, | wrote a blog post to explain my views on the design of command-line interface, Ih3.github.io/2022/09/28/a dd. Os Vix ® Dave Tang Retweeted NilsHomer We @... Sep 28 | am proud to announce the launch of ExcelBio! Driven by overwhelming demand from Biologists: build, manage, and execute your #Bioinformatic workflows all from your favorite GUI, Excel. We are proud to support Illumina SampleSheets as our first product. DM me for a demo! 1 © 288 © Retweeted Ming "To... We @t.. -Sep6 Ahybrid course covering best practices for bulk and single cell RNA-seq data analysis, diytranscriptomics.com DiY.transcriptomics - RNAseq course. Oo C450 o Dave Tang Retweeted Adamned... WF @... Aug 22 me: I need a passport so | can go to australia clerk: have you ever been convicted of a crime? mer is... is that still necessary On Om © Dave Tang a Retweeted Tom Wilks WF @.. Aug 10 Bohemian rhapsody for postdocs: Is this a real job? Or more like a PhD? Caught in short contracts No chance of stability your eyes up to Pis and see in just a postdoc i getno sympathy Because I'm easy come, easy go Stress is high Pay is low Om 9 3K ® Dave Tang Retweeted Ashley Ru... Wr @a.. Aug 4 By age 30, you should have a PhD and be several years into a post-doc with no house, no retirement savings, and no long-term job security in the field that you've devoted the last decade of your life. Oo © 19K © Dave Tang 8 Retweeted PositPBC |W @p... «Jul 27 We are excited to announce that RStudio, PBC will become Posit, PBC in October! More information here: posit.co RStudio is becoming Posit - Posit On OK @ ARCHIVES October 2022 September 2022 ‘August 2022 March 2022 January 2022 December 2021 September 2021 ‘August 2021 April 2021 October 2020 March 2020 February 2020 January 2020 December 2019 September 2019 April 2019 February 2019 January 2019 December 2018 ‘August 2018 June 2018 May 2018 February 2018 January 2018 October 2017 September 2017 ‘August 2017 July 2017 7 n 017 February 2017 January 2017 November 2016 October 2016 September 2016 ‘August 2016 July 2016 May 2016 March 2016 January 2016 December 2015 October 2015 ‘August 2015 July 2015 June 2015, May 2015 April 2015, March 2015 February 2015 January 2015 December 2014 November 2014 October 2014 September 2014 ‘August 2014 July 2014 June 2014 May 2014 April 2014 March 2014 2014 January 2014 December 2013 November 2013 October 2013 September 2013 ‘August 2013 July 2013, May 2013 April 2013 March 2013 February 2013 January 2013 December 2012 November 2012 October 2012 September 2012 ‘August 2012 July 2012, June 2012, May 2012 April 2012 March 2012 February 2012 January 2012 November 2011 October 2011 September 2011 ‘August 2011 July 2011 June 2011 yom January 2011 December 2010 November 2010, October 2010 META Log in Entries feed Comments feed WordPress.org INTENTIONALLY BLANK Copyright © 2022 Dave Tang's blog. All Rights Reserved, Boston Theme by FameThemes

You might also like