camacnei
camacnei

Reputation: 101

Create a new vector from single vector by manipulating Factors

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

Answers (4)

David Arenburg
David Arenburg

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

Rich Scriven
Rich Scriven

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

Henrik
Henrik

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

Ben Bolker
Ben Bolker

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

Related Questions