Reputation: 101
Data Format
Date Factor Value
2014-01-01 x 10
2014-01-01 y 2
2014-01-02 x 20
2014-01-02 y 5
I would like to return a vector that is the result of the value for factor x
divided by the value for factor y
for each day.
The result looking like:
Date Value
2014-01-01 5
2014-01-02 4
I am currently doing this with a nested for
loop that looks up the values by matching the dates. Just wondering if there is an easier way that I am missing?
Upvotes: 3
Views: 83
Reputation: 92282
Or using some heavy artillery (data.table
). If dd
is your data set, consider:
library(data.table)
setDT(dd)[, Value[1]/Value[2], by = Date]
## Date V1
## 1: 2014-01-01 5
## 2: 2014-01-02 4
If your data is not ordered, you can sort first and then run:
setkey(setDT(dd), Date, Factor)[, Value[1]/Value[2], by = Date]
## Date V1
## 1: 2014-01-01 5
## 2: 2014-01-02 4
Or just
setDT(dd)[, Value[Factor == "x"]/Value[Factor == "y"], by = Date]
## Date V1
## 1: 2014-01-01 5
## 2: 2014-01-02 4
Upvotes: 2
Reputation: 99331
You could also use unstack
, making use of the formula
argument.
Using @BenBolker's data dd
,
data.frame(Date = unique(dd$Date), Value = with(unstack(dd, Value~Factor), x/y))
# Date Value
# 1 2014-01-01 5
# 2 2014-01-02 4
Upvotes: 1
Reputation: 67778
If your data is ordered by Date and Factor, this will do. Select every second element of 'Value' using a logical vector, and calculate the ratio
ratio <- df$Value[c(TRUE, FALSE)] / df$Value[c(FALSE, TRUE)]
Put ratio in a data frame together with the dates
data.frame(Date = unique(df$Date), ratio)
# Date ratio
# 1 2014-01-01 5
# 2 2014-01-02 4
If necessary, start by ordering the data by Date and Factor:
df <- df[order(df$Date, df$Factor), ]
Upvotes: 3
Reputation: 226087
There are certainly other ways to do it but I like reshape2::dcast
.
Create example:
dd <- read.table(text="
Date Factor Value
2014-01-01 x 10
2014-01-01 y 2
2014-01-02 x 20
2014-01-02 y 5",header=TRUE)
Do it:
library(reshape2)
dd2 <- dcast(dd,Date~Factor)
with(dd2,data.frame(Date,Value=x/y))
Upvotes: 2