R for Bioinformatics

Lesson 4 of 14 · 10 min

Working with Data Frames

A data frame is R's version of a spreadsheet: a table with rows and columns that can hold different kinds of information at once. Almost every biological dataset you will meet, from gene expression tables to lists of patient samples, arrives as a data frame. Learning to build and inspect one is the single most useful skill in day-to-day bioinformatics.

Meet the data frame

In a data frame each row is one observation, such as a single gene, and each column is one measured variable, such as its chromosome or its expression level. Unlike a plain grid of numbers, different columns can hold different types, with text in one column and numbers in another. We build one with the data.frame() function.

r
genes <- data.frame(
  gene = c("TP53", "BRCA1", "EGFR", "MYC"),
  chromosome = c(17, 17, 7, 8),
  expression = c(8.2, 5.1, 12.7, 9.4),
  stringsAsFactors = FALSE
)

genes
   gene chromosome expression
1  TP53         17        8.2
2 BRCA1         17        5.1
3  EGFR          7       12.7
4   MYC          8        9.4

The arrow <- assigns the result to a name, here genes, so we can reuse it later. Inside data.frame() each argument becomes a column, and c() combines several values into one column. Adding stringsAsFactors = FALSE keeps the gene names as plain text rather than converting them to R's factor type, a special format R uses for categorical data; modern R already does this by default, but stating it makes the intent clear.

Inspecting a data frame

r
str(genes)   # structure: types and a preview of every column
head(genes)  # the first rows (up to 6 by default)
nrow(genes)  # how many rows
ncol(genes)  # how many columns
'data.frame':	4 obs. of  3 variables:
 $ gene      : chr  "TP53" "BRCA1" "EGFR" "MYC"
 $ chromosome: num  17 17 7 8
 $ expression: num  8.2 5.1 12.7 9.4
   gene chromosome expression
1  TP53         17        8.2
2 BRCA1         17        5.1
3  EGFR          7       12.7
4   MYC          8        9.4
[1] 4
[1] 3
r
# The $ operator pulls out a single column by name
genes$gene

# A column is just a vector (an ordered list of values),
# so numeric functions like mean() and summary() work on it directly
mean(genes$expression)
summary(genes$expression)
[1] "TP53"  "BRCA1" "EGFR"  "MYC"  
[1] 8.85
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  5.100   7.425   8.800   8.850  10.225  12.700 

Try it yourself: Rebuild the genes data frame from the first code block, then add a new column with genes$length_kb <- c(20, 81, 188, 5). Run ncol(genes) to confirm it now reports 4 columns, then run mean(genes$length_kb) to find the average gene length in kilobases.