Data Frames

Let’s recap what we know about data frames already.

We have learned that a data frame is a specific type of list that stores tabular data. We also learned how to use the data frame function (data.frame()). Now that we have learned about matrices, we can relate them to data frames. Data frames have rows and columns, similar to matrices. As we have talked about before, data frames can have elements that are different data types, but each column needs to be the same data type. Also, the vectors in a data frame need to be the same length. Let’s go over an example.

Create a data frame of the list, named drinks, containing numbers 4 through 7, and the words “water”, “milk”, “soda”, and “juice”. Let’s also name the elements of the list. We’ll call the numbers 4 through 7, “num” and we’ll call the words “water”, “milk”, “soda”, and “juice”, “liquid”.

num <- 4:7
liquid <- c("water", "milk", "soda", "juice")
drinks <- list(num, liquid)
data.frame(c(num, liquid))
##   c.num..liquid.
## 1              4
## 2              5
## 3              6
## 4              7
## 5          water
## 6           milk
## 7           soda
## 8          juice

The data frame we have just created is a list of all values. We can also create the same data frame but with rows and columns, similar to a matrix. Our rows will be our observations and our columns will be our variables. In this case, our variables would be num and liquid. To do this, we would remove the c() from the above code chunk. Let’s see what that would look like.

num <- 4:7
liquid <- c("water", "milk", "soda", "juice")
drinks <- list(num, liquid)
data.frame(num, liquid)
##   num liquid
## 1   4  water
## 2   5   milk
## 3   6   soda
## 4   7  juice

Subsetting Data Frames

Let’s say we have data from 4 people in a store. The first persons name is Joe. Joe is 17 years old and does not have siblings. The second person is Mary. Mary is 15 and has a sister. The third person is Brad. He is 20 years old and has 2 brothers and 1 sister. Finally, the fourth person is Nancy. She is 13 years old and has no siblings. Let’s say we wanted to make a data frame with this information. Let’s use our previous knowledge to do this.

names <- c("Joe", "Mary", "Brad", "Nancy")
age <- c(17, 15, 20, 13)
sibling <- c(FALSE, TRUE, TRUE, FALSE)
people <- data.frame(names, age, sibling)
people
##   names age sibling
## 1   Joe  17   FALSE
## 2  Mary  15    TRUE
## 3  Brad  20    TRUE
## 4 Nancy  13   FALSE

When we run this code chunk, we can see the table including the person’s name, age and if they have siblings or not. Let’s say we want to see how old Mary is. We know Mary is the person whose data is in the second row, and age is the second column. Similar to when we subset matrices, we write the code below.

people[2,2]
## [1] 15

We see that our code gives us 15, which is in fact the age of Mary. This is a vector of length 1. We can also use the name of the column we want to see the data from and obtain the same answer. Run the code chunk below to see this.

people[2, "age"]
## [1] 15

If we only wanted to find information about Brad, we can write a code similar to what we did when we used matrices.

people[3,]  # Brad is the third person in the list, so his information is in the third row.
##   names age sibling
## 3  Brad  20    TRUE

When we run this code chunk, we obtain a data frame including all the information on Brad.

If we wanted to see the age of all the people we have data on, we would use a similar approach.

people[,2]    # We could also write the code "people["age"]" and obtain the same results
## [1] 17 15 20 13

We now obtain a vector of the ages of the people from the store.

If we wanted to find the names and ages of the people from rows 1 and 2, we write a code like the one below.

people[c(1,2), c("names", "age")]
##   names age
## 1   Joe  17
## 2  Mary  15

We obtain a subset of the original data frame.

Note: Similar to matrices, the number before the comma in the square brackets represents the row number and the number after the comma represents the column number.

Remember how important the comma was when working with matrices. When we included the comma and had an empty space before or after it, we wanted a specifc row or column. When we did not include the comma, and only had a number in the square brackets, we obtained a single element. Just like matrices, the comma is also important in data frames. When we forget to include the comma when we working with data frames, we do not obtain a specific element. Let’s see what happens with data frames.

people[2]
##   age
## 1  17
## 2  15
## 3  20
## 4  13

In this case, we obtain the second column in the data frame. If we want to find the list of all the names, but we do not know which column the names are in, we can write a code similar to the one above.

people["names"]
##   names
## 1   Joe
## 2  Mary
## 3  Brad
## 4 Nancy

When we run this code chunk, we obtain a data frame of the names.

As we saw in module 4, where we first introduced data frames, we can use $ to find the contents of a specific element. Let’s do this with our data frame “people” to find the contents of sibling.

people$sibling
## [1] FALSE  TRUE  TRUE FALSE

We can see that this creates a vector of the siblings column of our data frame.

Extending Data Frames

If we wanted to add a column (variable) to our data frame we could also do that. Let’s say we know the height (in inches) of each person. Joe is 67 inches tall, Mary is 64 inches tall, Brad is 68 inches tall, and Nancy is 60 inches tall. We can add this column using cbind() like we have done previously.

height <- c(67, 64, 68, 60)
cbind(people, height)
##   names age sibling height
## 1   Joe  17   FALSE     67
## 2  Mary  15    TRUE     64
## 3  Brad  20    TRUE     68
## 4 Nancy  13   FALSE     60

When we run this code chunk, we can see that the column “height” has been added to the data frame.

Another way that we can add a column to the data frame is shown in the code chunk below.

height <- c(67, 64, 68, 60)
people$height <- height
people
##   names age sibling height
## 1   Joe  17   FALSE     67
## 2  Mary  15    TRUE     64
## 3  Brad  20    TRUE     68
## 4 Nancy  13   FALSE     60

Note: Notice how when we created the height vector, we typed the numbers in the order that the person’s name associated with that height appears.

Let’s say another person, Mike, enters the store. Mike is 18 years old, has 1 brother, and is 70 inches tall. How would we add Mike’s data to our already exisiting data frame? We cannot put all of Mike’s information into a vector because his information consists of different data types. In order to add his information, we need to create a data frame with his information and add that data frame to our existing data frame “people”. Let’s see how we do this.

mike <- data.frame("Mike", 18, TRUE, 70)
#rbind(people, mike)

When we remove the # and run this code chunk, we obtain an error. This is because we did not name the elements of our data frame “mike”. Let’s fix that and see what our data frame “people” looks like now.

mike <- data.frame(names = "Mike", age = 18, sibling = TRUE, height = 70)
person <- rbind(people, mike)
person
##   names age sibling height
## 1   Joe  17   FALSE     67
## 2  Mary  15    TRUE     64
## 3  Brad  20    TRUE     68
## 4 Nancy  13   FALSE     60
## 5  Mike  18    TRUE     70

When we run this code chunk, we can see that Mike’s information is added to our data frame. Notice that we also used rbind() to add Mike’s information to our data frame. We named the data frame including Mike’s information as “person”, so we can refer to it later. If we did not name it, and we used “people”, Mike’s information would not be included in our data frame.

Sorting in Data Frames

Let’s say we wanted to order Joe, Mary, Brad, Nancy and Mike by height. We can use the sort function (sort()) to do this. Let’s see how that works.

sort(person$height)
## [1] 60 64 67 68 70

This function prints a vector with the heights in order of shortest to tallest. It does not tell us what height belongs to which person though. To do this, we need to use the order function (order()).

ranks <- order(person$height)
ranks
## [1] 4 2 1 3 5

This gives us a vector that shows which row has the person who is the shortest and ascends to the tallest person. Still, this does not tell us the names or heights of the people in our sample. Let’s see how we do this.

ranks <- order(person$height)
person[ranks,]
##   names age sibling height
## 4 Nancy  13   FALSE     60
## 2  Mary  15    TRUE     64
## 1   Joe  17   FALSE     67
## 3  Brad  20    TRUE     68
## 5  Mike  18    TRUE     70

The code chunk above prints a data frame consisting of the information of Joe, Mary, Brad, Nancy, and Mike in order of shortest to tallest.

Another way we can do this is shown below.

person[order(person$height),]
##   names age sibling height
## 4 Nancy  13   FALSE     60
## 2  Mary  15    TRUE     64
## 1   Joe  17   FALSE     67
## 3  Brad  20    TRUE     68
## 5  Mike  18    TRUE     70

If we wanted to see our data from tallest person to shortest person, we would include decreasing = TRUE into our code chunk. Let’s see how this would look.

person[order(person$height, decreasing = TRUE),]
##   names age sibling height
## 5  Mike  18    TRUE     70
## 3  Brad  20    TRUE     68
## 1   Joe  17   FALSE     67
## 2  Mary  15    TRUE     64
## 4 Nancy  13   FALSE     60