Reputation: 596
I have a very simple dataframe an its is like this:
id ts val
A 2013-01-01 00:00:00 12
A 2013-01-01 00:00:00 543
B 2013-01-01 00:00:00 76
B 2013-01-01 00:00:00 76
A 2013-01-01 01:00:00 11
C 2013-01-01 01:00:00 42
C 2013-01-01 02:00:00 48
What I want to do is to rescale all values, so they can be between 0 and 1, but grouping by id. In other words, I need to calculate min's and max's for each block of id and then rescale each row by taking its value, subtract from the min group value and divide by min-max. In R form:
function rescale01 <- function(curr, min, max) {return (curr-min/max-min)}
I found a way to get min's and max's from this dataframe, but is too cheesy:
ddply(df[,c(1,3)], "tag", function(x){
y <- subset(x, select= -tag)
c(apply(y, 2, min), apply(y, 2, max))
})
Can you suggest a better way to achieve what I need?
Thanks!
Upvotes: 1
Views: 197
Reputation: 206576
The base function ave()
would also work just fine (using @Romain's sample data)
df <- data.frame( id = rep( c(1,2), each = 5 ), x = 1:10 )
df$rescaled <- with(df, ave(x, id, FUN=function(x) {(x-min(x))/(max(x)-min(x))}))
df;
Upvotes: 1
Reputation: 17642
Perhaps using dplyr::mutate
:
> df <- data.frame( id = rep( c(1,2), each = 5 ), x = 1:10 )
> group_by(df, id) %>% mutate( x = ( x-min(x) ) / ( max(x) - min(x) ) )
Source: local data frame [10 x 2]
Groups: id
id x
1 1 0.00
2 1 0.25
3 1 0.50
4 1 0.75
5 1 1.00
6 2 0.00
7 2 0.25
8 2 0.50
9 2 0.75
10 2 1.00
Upvotes: 2