I would like to make a data.frame in R with some columns having multiple values (same number of variables for all rows). For example, here is a data frame with two columns (cars and price), note that column price has three values for each row.
cars price
F 1000,2000,3000
GM 2000, 500, 1000
The second question:
Now I want to apply the same function to each value in the price column, how can I do that? Let's say I want to create another column with doubled values of price column.
data.frames are simply lists, and as such, they can also be lists of lists.
cars <- c("FORD", "GM")
price <- list( c(1000, 2000, 3000), c(2000, 500, 1000))
myDF <- data.frame(cars=cars, price=cbind(price))
myDF
# cars price
# 1 FORD 1000, 2000, 3000
# 2 GM 2000, 500, 1000
then to execute a function on all values of price in a given row:
# execute on ALL PRICES at once
mean(unlist(myDF$price))
# [1] 1583.333
# execute on each set of PRICES per row:
lapply(myDF$price, mean)
# [[1]]
# [1] 2000
#
# [[2]]
# [1] 1166.667
It gets cummbersome and there are usually better ways to accomplish the same goal.
One alternate method is to simply use the price list as your dataset and name the elemens according to the cars column:
names(price) <- cars
price
# $FORD
# [1] 1000 2000 3000
#
# $GM
# [1] 2000 500 1000
In this case, your *ply statements would have the names of the cars already assigned to them and it would be slightly less typing:
lapply(price, mean)
# $FORD
# [1] 2000
#
# $GM
# [1] 1166.667
Al alternate method is to use a long data.frame or data.table:
# transforming to long:
myDF <- data.frame("cars"=rep(cars, times=lapply(price, length)), "price"=unlist(price, use.names=FALSE))
myDF
Then you can use the by argument to execute functions across all prices in a group:
by(data=myDF$price, INDICIES=myDF$cars, FUN=mean)
# or using with:
with(myDF, by(price, cars, mean))
Here is the same approach, but using data.table (which has by built in)
library(data.table)
myDT <- data.table(myDF, key="cars")
myDT[, mean(price), by=cars]
# cars V1
# 1: FORD 1501.250
# 2: GM 1166.667
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With