Introduction

Author

Dr. Robert I. Colautti

Published

May 10, 2026

In Biology, there are two dominant programming languages: Python and R. Thousands of hours have been wasted arguing the merits of one programming language over another. The truth is that there is a lot of similarity and it’s very easy to move from one to the other.

The completely honest truth is that no programming language is perfect. Computers are ultimately just tiny transistors that either hold an electric charge or not. Translating transistors to useful work involves a number of trade-offs, the main one being speed versus interpretability. The faster a computer language runs, the less intuitive it is for somebody to understand what the program does just by reading the code.

There are many other programming languages used in Biology. C/C#/C++ and Java are popular in computer science because they provide a high level of control, but this comes at a cost of more abstraction and a steeper learning curve. Bash programming in Unix/Linux/GNU is all but necessary for high-performance computing on remote servers, but in biology it is most often used to automate file management and to run programs written in other languages. Julia is gaining momentum for mathematical modellers, but it is still in its infancy. Perl is an older programming language that was popular for bioinformatics but its popularity has faded with the growth of Python.

This book focuses on R because it is more commonly used in published statistical analyses in Biology, it has a nice set of free programming aids, and because it has a healthy and inclusive community of programmers and users. One common complaint in online chat groups is that R programs run slower than Python. But this is mostly true for beginner programmers, who don’t know how to optimise R programs. For example, the R can execute C++ scripts, which run much faster than base Python. More importantly, R and Python share a very similar programming style, making it easy to switch to Python once you are comfortable programming in R.

As you will see, it is very easy to walk through the fundamentals and generate graphs and statistical analyses with just a few hours of practice. In fact, you will learn all of the essentials when you complete just the first section of this book. This simplicity comes at a cost of slower run-times (for beginners) and less flexibility than Python, but this is usually not a problem when you are writing relatively simple computer programs. In fact, it is possible to use R to mix and run code from other programs including Python and C++. More importantly, concepts like data objects, function and packages are conceptually very similar between R and Python, making it easy to move from one language to the other. The truth is that they are both good languages and anyone who tells you that language A is better than B is simply showing their ignorance about language B.

Advice

If you’ve completed a few years of any undergraduate program in biology, then you’ve probably developed a good strategy for studying various subjects in Biology. Maybe it involves reading the textbook, attending lectures, and making notes that you review before the big test. Those learning skills are valuable and transferable to many different scenarios, but I’m afraid that coding is different.

If this is your first attempt to learn how to code, then it’s important to understand HOW NOT TO LEARN how to code. You won’t learn by reading this textbook, or any other textbook, or by watching videos on the internet, or by attending lectures about coding. If you are serious about learning to code, then you need to participate and actively take control of your learning by typing along with the examples in this book. Learning to code is not like learning about biology. It’s more like learning how to ride a bike or play an instrument. That is to say, it is good to read, and watch videos, and attend lectures but ultimately you have to practice writing your own code.

Consider why we call R a programming language. When I teach this content to biologists, I often begin with a poll of students to see who has learned to speak more than one language. I then ask:

Question: How did you become fluent in a second language?

Some common themes in the answers tend to be:

  • Immerse yourself
  • Study, read, listen
  • Try something new, fail, correct errors, repeat
  • Practice, practice, practice!

How do you become fluent in a programming language? Pretty much the same way:

  • Immerse yourself
  • Study, read, and type everything out!
  • Try something new, fail, correct errors, repeat
  • Practice, practice, practice!

Learning a new language is not easy. Learning a programming language is not easy either. Here are a few specific tips to become fluent in R:

  1. Get organised and PLAN. Use a personal calendar and schedule sufficient time to deal with error messages. This is important to accept, though it can be difficult: troubleshooting your code often takes longer than writing your code, especially when you are starting to learn.

  2. Apply what you learn. You will start to develop a toolbox of coding techniques from day one. Look for opportunities to apply them whenever you can. Try to re-frame small projects or tasks in terms of what you can address with your ever-expanding R toolkit. Even if it takes a lot longer to code than to use other methods, the extra time will reinforce your coding skills, saving time in the long run. Take time to think about what coding tools you can apply.

  3. Experiment. Try new things, make mistakes, solve problems.

  4. Protect your coding time. Set aside large blocks of time (2+ hours), to immerse yourself in your coding lessons or project. Make it a priority, at least for the first section of this book. That will help you establish a solid foundation and the ability to get things done in R. Once you have that basic set of skills, it is much easier to build coding knowledge and expertise.

  5. Focus. Eliminate distractions. Turn off your notifications. Put your phone and computer on ‘airplane mode’. Do whatever it takes to work without interruption.

  6. Montage. Get some good headphones with white noise or instrumental sounds (no lyrics) to block out distractions. Here are some options that I like to listen to, depending on mood:

  • Baroque/Classical
  • Smooth Jazz
  • Scores from epic movies and video games
  • Electronic (ambient, house, lofi)
  • https://coffitivity.com/
  1. Learn to Troubleshoot. If you get stuck, Google: “How do I ______ in R”. Look for answers from a website called Stack Overflow: (https://stackoverflow.com/). If you can’t figure out what an error means, paste it into Google. Again, look for answers from Stack Overflow. A generative AI model like GPT can help too, but that’s a bit different so it gets its own section, below.
  1. Socialize. Find a coding support group or find a few others to form your own group. Discuss problems and successes. Read other people’s code to see how they tackle problems. Rarely is there one single ‘right’ way to code something, and seeing how other people tackle a problem is a great way to learn new coding skills.

  2. Git ’er done. When you are starting out, the ‘right’ way to code is whatever it takes to get the code to do what you want. Don’t let perfection be the enemy of the good: messy code that works is 100% better than elegant and efficient code that never runs.

  3. Improve. As you get more comfortable you can start to think about cleaner, clearer, more efficient ways to code. As you advance, look for ways to do the same thing faster and with fewer lines of code.

  4. Embrace Failure. I can’t stress this enough. Everyone fails! Even after 10+ years of programming experience, I often make coding errors, and a decent amount of my time is spent dealing with error messages and unexpected output. Your instinct might be to get annoyed at the delay, or at having to ‘waste’ time troubleshooting. Instead, try to see every error as a valuable learning opportunity. Dealing with errors is time well spent!

  5. Read the documentation for the function or package you are using. Don’t worry if you don’t understand everything. You are learning a new language after all. Be sure to take the time to read it slowly and try to understand as much as you can. It gets easier to understand with practice. Try searching online for terms or phrases that are not familiar to you. You will come across these again in the future, so you are investing time now for future payoff. In addition to the built-in help in R, often the repository on The Comprehensive R Archive Network (CRAN) (https://cran.r-project.org/) or Bioconductor (https://www.bioconductor.org/) will include vignettes or tutorials as pdf files with worked examples. AI can help here too, as discussed in the next section.

  6. Use AI Effectively. With the rise of Large Language Models (LLMs) and other forms of artificial intelligence (AI), it’s time to re-think how we teach and learn coding. We’ll expand on this in the next section.

Use Generative AI

The rapid advancement of Artificial Intelligence (AI), particularly Large Language Models (LLMs) like the Generative Pre-trained Transformer (GPT), is having a profound effect on the way that we work and learn. Just as LLMs can help with writing and research, they can also be used to write and edit code. Programs like ChatGPT, and Bing Copilot use the GPT LLM, others like Code Llama, and StarCoder have different LLMS, but all can write effective code (. There is no question that LLMs and other forms of AI will continue to develop into indispensable tools for biological research. If you are reading this book to learn how to code, these tools can act like a personal tutor to help you learn to code faster and more effectively, and potentially introduce you to new techniques. It’s likely these tools will only get better in the future, so it’s worth incorporating them into your learning process now. What is the best way to use these tools to enhance learning?

As of this writing, there are two major issues with LLMs that can interfere with your learning. The first problem is related to an important and recurring theme in this book: The best way to learn to code is to write code yourself, type everything out, try different things, make mistakes, and learn how to fix them. Struggling to write and proofread your own code can be slow, tedious, and frustrating, but in my experience it is actually the most efficient way to develop competency. LLMs are not programmed to help you learn, they are just fancy statistical models that have no vested interest in your learning or career goals. You can ask a LLM to write code for you, but I strongly suggest you avoid that when you are first learning how to code. Instead, try to use LLMs like a tutor by asking questions that inform your own understanding. Some specific tips are provided below.

Apart from hindering your learning, the second major issue with LLMs is that they will often give you bullshit without warning. Computer scientists say these models ‘hallucinate’, but ‘bullshit’ is arguably a more accurate term. The word bullshit has a technical definition in academic circles, thanks to Harry G. Frankfurt in his 2005 philosophy book On Bullshit. Briefly, he points out that bullshit is similar to a lie except that there is no regard for the truth. Whereas a liar is aware of the truth and tries to direct people away from it, a bullshitter will happily mix truth with misinformation and disinformation to achieve their goals.

In Calling Bullshit: The Art of Skepticism in a Data-Driven World, Carl Bergstrom and Jevin West apply the concept of bullshit to data analysis, showing how choices about data analysis and presentation can be mislead viewers, sometimes unintentionally, as a result of the assumptions and choices people make analyzing and visualizing data. They also suggest strategies for detecting bullshit in data analysis in a very entertaining way with minimal jargon. I highly recommend this book. I also recommend Frankfurt’s book, which a small pocket-sized book. Both are easy to read.

In a 2023 article for Undark Magazine, Carl Bergstrom and Brandon Ogbunu argue that bullshiting is a more accurate term than hallucinating for ChatGPT:

“When AI chatbots flood the world with false facts, confidently asserted, they’re not breaking down, glitching out, or hallucinating. No, they’re bullshitting.”

So the second problem with using LLMs is that they might teach you something that is subtly or completely wrong.

Despite the issues with LLMs, it’s likely that these models will only improve, and future coders will use AI regularly in their workflows. Therefore, it’s worth learning how to use LLMs to write effective code. The key for you at this point is to use AI to save you time and effort, without it getting in the way of your learning by doing your hard work for you, or by teaching you bullshit. Here are some tips when you are first starting to learn to code:

  • DO Try to figure it out yourself, ask AI for help only when you get stuck.
  • DO Ask AI for help interpreting warning or error messages in your code.
  • DO Read the R help yourself. It’s difficult at first, but it gets easier. Ask AI for help with terms or concepts that you don’t understand in the R help.
  • DO Ask AI for feedback on your code, but don’t use code that you don’t understand. Read the code carefully with your bullshit detectors turned up to 11.
  • DO Ask AI to explain code to you, as you would ask a tutor.
  • DON’T Ask AI which packages or functions you should use. Unless you like to spend lots of extra time memorizing functions and package names, the best way to learn them is through repetition. It’s also important to learn how to apply what you know, and this can only be learned if you spend time thinking about what you know and how you can apply what you know to solve a given problem.
  • DON’T Ask AI to write code for you. Not only will it make it affect your ability to learn to write effective code, it may produce complete bullshit.

Learn by Doing!

As you work through these self-tutorials, don’t just read them. I can’t stress this enough: take the time to type out the commands in your R (Studio) console and make sure you get the same output. The simple act of typing it out will send messages to your brain saying “hey, pay attention, this is important!” If you get an error, even better! Read the error carefully, then compare what you typed to what is in the tutorial. Once you find what is different, you will learn what that error means.

About 70-90% of coding time is dealing with errors when you start learning to code. This can be difficult to accept because our experience in a typical biology course is quite different.

What to Expect

Learning to code is a lifelong journey. There is always more to learn and new ways to improve. If the beginning of your journey is anything like mine was, it might be characterised by fouroverlapping stages:

  1. Utter bewilderment – reading code is like reading a foreign language. All these letters and symbols are meaningless to you.

  2. Understanding – you can look at a function and have a decent idea of what it does and how to use it, but you don’t understand most of the arguments. You usually rely on default arguments because you don’t understand them well enough to know any better. But, at least you can get stuff done!

  3. Competence – you can write your own code from scratch, without needing to look up examples, and you are able to carefully review and apply arguments. You rarely trust default arguments, especially for more complicated functions.

  4. Expertise – you write your own functions and complicated analysis pipelines. You know R well enough to help others. Maybe you have published R functions, pipelines, or packages.

A word of advice when you are starting out: Don’t confuse deep understanding with coding competence – this is a common mistake that students make. It’s relatively easy to learn how to understand code that is shown to you, but it’s quite another skill to learn the names and arguments of useful functions and apply them to solve problems and address biological hypotheses. That doesn’t mean you need to memorize every function – though memorization can help. A good strategy to move from understanding to competence is to take the extra time and make the effort to type out the code that is shown to you, even when you can look at it and understand what it does. I know I’m being repetitive, and it’s because I am trying to instill this enough that you won’t ignore or forget it. The simple act of typing out the code is what will help to solidify it in your brain.

Translational Coding

There is often a mismatch between the knowledge acquired through a university degree and the skills that employers need in their workforce. That is, newly minted university students have a lot of knowledge and skills for learning, but often struggle with goals laid out by employers or even to set such goals in entrepreneurial endeavours or thesis/dissertation research.

In the computing world, the disconnect between learning and application can happen when students have acquired knowledge of coding algorithms and tools, but learn to apply these tools within a ‘sandbox’ created for teaching purposes. The sandbox is a clean and well-groomed programming environment with pre-loaded software and examples, curated by the educator. The sandbox lacks the messiness and ambiguity that define real-world applications, and the student doesn’t gain experience working in less comfortable but more realistic coding environments. The sandbox approach is commonly used in both university and online courses (e.g. Udemy, Coursera, Datacamp, Skillshare).

A typical teaching sandbox will probably include pre-installed software with ‘clean’ data defined by a well-defined data structure without errors or missing observations. It will probably have a clear and singular path from problem to solution. This approach has the advantage of efficiency – both for the educator and for the learner. The learner can be guided to move efficiently through key learning objectives while minimising unexpected bugs or problems that can slow progress and take significant time for educators to deal with. The sandbox creates a more homogeneous experience that is more efficient for tracking progress and assigning grades. The great thing about sandboxes is that you feel like you are learning faster, but it can be an illusion. The trade-off is that sandbox learning does a poor job preparing you for the messy realities of coding with real programs, installed on real computers, to work on real data.

An alternative to the sandbox approach is translational coding, which borrows the term from translational medicine. Translational medicine is a multidisciplinary hybrid between research and application that directly connects medical researchers to the needs of patients. By analogy, translational coding tries to directly connect coding skills and tools to the needs of potential employers.

This will not be pleasant for you, the learner, at first. The sandbox approach is popular with learners because it is relatively quick and painless with minimal time needed for researching, planning, debugging, and other forms of problem solving. There is value to learning to work quickly and efficiently, but translational coding requires an additional level of learning – learning to deal with problems that arise in the real-world. This includes dealing with errors at every stage, from installing software to problems hidden among thousands of lines of data or code. This can be frustrating at first, and it will absolutely slow down your progress. There are three key things to remember when this happens:

  1. Every error, problem, or roadblock is a learning opportunity. These are the challenges that every learner must overcome to complete the task. In addition, there are implicit challenges that may be unique or shared by only a few learners – a particular typo in the code, an error importing or saving, an unidentified error in your dataset. These implicit problems may feel ‘unfair’ because not every learner has to deal with the same problems at the same time. Over time however, these will tend to average out so that everyone will make similar mistakes, albeit at different times.

  2. You can learn to budget your time to account for these potential problems. This is an important and highly-transferrable skill! Start a problem or assignment as soon as possible. Give yourself time to take a break and come back to a problem when you get stuck. When you estimate how long an assignment will take, don’t just look at the explicit goals. Also add time for the potential problems, which are hard to predict and can take much longer to address.

  3. Time devoted to a new problem pays off in the future. The first time you encounter a problem will take you the longest to solve. If you invest the time and energy to work it out, then every subsequent time you encounter a similar problem, it will be much faster and easier to solve. If you take the time to read the error or warning, think about it, and investigate it, then you will know how to recognise and deal with it in the future. In this way, coding errors and other problems tend to balance out among learners over time. Some learners will encounter a problem early and struggle while others move ahead, until they encounter the same problem, evening the playing field.

The most important thing is to embrace the challenge! Don’t let yourself get discouraged.

Now, let’s get set up to start coding in R.

Setup

R

Before you begin these tutorials, you should install the latest version of R: (https://cran.r-project.org/)

Versions are available for Windows, MacOS and Linux operating systems. We haven’t even started coding yet and already we can see one of the advantages of learning to code in R. It doesn’t matter if you have a Macintosh computer or if your laptop runs on Microsoft Windows, in fact, we could just as easily be working on a remote server running on Unix. R makes it easy to move code across computing platforms quite easily, as long as R is installed there.

R Studio

You should also install R Studio: (https://rstudio.com/products/rstudio/download/#download)

R Studio is an Integrated Development Environment (IDE). What is an IDE? The Integrated part refers to the R programming language, which is integrated into R Studio, so no need to open R separately. The Development Environment part means that R Studio is like your own little home office, with many useful features to help us write better code in less time. This will make sense if we dive in and start using it. Once you install R Studio, go ahead and run the program.

The first time you run R Studio, you will see several helpful tabs arranged across three (or possibly four) different window frames within the R Studio program. Several windows have more than one tab at the top, which you can click to access. Here is a quick overview of the more useful ones (some of this will make more sense after you work through the first few chapters of the tutorial):

  • Environment keeps track of all of the objects in your programming environment.
  • History keeps track of the code you have run.
  • Files similar to the Finder (MacOS) or File Explorer (Windows), starting with the working directory.
  • Plots are where your plots are created.
  • Packages show which packages you have installed, and which have been loaded.
  • Help provides documentation for R functions.
  • Console is important enough to get its own section.

Console

The console is one of the most important tabs in R Studio. If you haven’t changed any settings in R Studio, then the console should be the main tab that opens on the left when you first start R Studio. You’ll see a little chevron (>) with a cursor after it. This is the R Console, which is the part of R Studio that actually runs the R program. Everything in this window shows you what would happen if you ran the code outside of R Studio, for example on a high performance computing cluster like the ones maintained by Compute Canada, Microsoft Azure, Amazon Web Services, or Queen’s University’s own Centre for Advanced Computing. Everything else in R studio is built around helping you to manage and perform tasks in R, as implemented through the R Console.

R Script

To run an R script, you can just type functions into the console. However, it is very hard to keep track of everything you do if you only use the console. In R Studio you can click File-->New File-->R Script. This will open a new tab window called Untitled. This is where you can write and save the text of your R script. A script is really just a text file that will run in R and therefore we often save it with a .R suffix instead of a .txt. However, it’s important to understand that this is just a regular text file that you can open in just about any text reader. Try typing something into your R script – don’t worry for now if it is just some random text. Note that you can Save this file.

You can try typing something in your R script, like:

# My first R Script

on the first line (be sure to include the #), then

2+2

on the second line.

Nothing happens yet. That’s because it is just a text file. To run the script, we must send the text from the R script tab to the R console tab. There are a few ways you could do this:

  1. Copy and paste manually. This works fine, but there are more efficient options.

  2. Highlight the code you want to run and click the Run button on the top-right corner of the script tab. The run button sends the highlighted text from the script to the console.

  3. If you click the Run button without highlighting text, it will send whatever text is on the same line as your cursor.

  4. If you press Ctl + Enter (Windows) or Cmd + Return (Mac) it will do the same thing – this is the shortcut for the Run button.

  5. There are other options if you press the tiny triangle next to the Run button, including Run All.

  6. Ctl/Cmd + Shift + Enter/Return is a shortcut for Run All.

Packages

Packages in R contain functions – small programs that contain functions you can use. A few are loaded automatically when you start R, including the stats and base packages. One really good package is called tidyverse. The tidyverse package contains many useful functions for visualizing and working with different types of data. You’ll need to make sure you are connected to the internet and that your connection to the internet won’t be interrupted during the download.

WARNING! This may take a long time to run. Make sure your computer is not going to run out of battery or shut off during the installation.

To install the tidyverse packages, open R Studio and look for the Console tab. Type this into your console:

install.packages("tidyverse")

R might ask you if you want to update other packages that tidyverse uses. If that is the case, type a to select ‘all’ and then sit back with your coffee or tea until it is done. Be careful not to quit early. Sometimes it looks like it is done because the text messages are not updating, but that’s because there is something happening in the background. When everything is done, you should see the chevron > in the R console, beckoning for your input.

On a more general note, the install.packages() downloads the package and saves it on your computer. You only need to do this one time, though you may want to do it periodically to update to the latest version of the package.

Once a package is installed on your computer, it will be available to run in R with the library() command. You’ll see examples of this throughout the book.

That’s it! You’ve just started and you already wrote your first R script and downloaded and installed your first R package! Go you!

Now, let’s get coding…