Almost every analysis in R operates on a data frame.
A data frame is a list of equal-length column vectors, each with its own type: a table with rows as observations and columns as variables. Build one with data.frame(name = c("a", "b"), age = c(30, 25)); R ships example data such as mtcars and iris.
Inspect with head(df), str(df), summary(df), nrow(df), ncol(df) and names(df).
Columns are list elements: df$age or df[["age"]] gives a vector. Subset rows and columns with df[rows, cols]:
df[df$age > 26, ]keeps matching rows (note the comma: an empty column index means all columns).df[, c("name", "age")]selects columns.df[order(df$age), ]sorts rows.
Single-column subsets like df[, "age"] simplify to a vector; add drop = FALSE to keep a data frame. subset(df, age > 26, select = name) is a convenient interactive alternative.
Add or change a column by assignment, df$senior <- df$age > 60, and add rows with rbind. merge(a, b, by = "id") joins two data frames, and aggregate(age ~ group, data = df, FUN = mean) computes group summaries.
Tibbles (from the tidyverse) are data frames with stricter, friendlier behaviour: they never simplify to vectors and print compactly.
Example
df <- data.frame(name = c("Ana", "Bo", "Cy", "Di"),
age = c(31, 25, 47, 25),
team = c("x", "y", "x", "y"))
print(nrow(df)) #> [1] 4
print(df[df$age > 26, "name"]) #> [1] "Ana" "Cy"
print(df[order(-df$age), ][1, ])
#> name age team
#> 3 Cy 47 x
df$senior <- df$age > 40
print(sum(df$senior)) #> [1] 1
print(aggregate(age ~ team, data = df, FUN = mean))
#> team age
#> 1 x 39
#> 2 y 25
print(class(df[, "age"])) #> [1] "numeric"
print(class(df[, "age", drop = FALSE])) #> [1] "data.frame"Remember
- A data frame is a list of equal-length columns
df[rows, cols]; an empty index means alldf$colis a vector;drop = FALSEkeeps a data frame
Watch out for
- Forgetting the comma in
df[df$x > 1, ], which selects columns instead of rows.