I have a data.frame as follows: a 3 a 2 a 1 b 3 b 2 c 2 c 3 c 1 c 1 Each factor (a, b, c) should be monotonically decreasing, notice that factor 'c' is not. I could use some help to figure out how to form a logical structure (mostly just syntax), that will check each 'next value' for each factor to see if it is less than the previous value. If it is less than the previous value, do nothing, else subtract 'next value' from 'current value', add that amount to the starting value and each previous value to the 'next value' is greater than 'previous value'. So basically the data.frame would look like: a 3 a 2 a 1 b 3 b 2 c 3 c 3 c 1 c 1 Thanks for your help! __________________________________ Christopher P. Peters Research Associate Center for Energy Studies http://www.enrg.lsu.edu/staff/peters Energy, Coast & Environment Building Louisiana State University Baton Rouge, LA 70803 Telephone: 225-578-4400 Fax: 225-578-4541 [[alternative HTML version deleted]]
This works, but I'm still hunting for a more elegant final step:> test <- data.frame(A=c("a", "a", "a", "b", "b", "c", "c", "c", "c"), B=c(3,2,1,3,2,2,3,1,1)) > test2 <- lapply(split(test$B, test$A), sort, dec=TRUE) > test3 <- data.frame(A=rep(names(test2), times=lapply(test2, length)), B=unlist(test2))It will also group data by factor, which was already done in your example. Sarah On Sun, Jun 19, 2011 at 4:20 PM, Christopher Peters <cpeter9 at lsu.edu> wrote:> I have a data.frame as follows: > > a ?3 > a ?2 > a ?1 > b ?3 > b ?2 > c ?2 > c ?3 > c ?1 > c ?1 > > Each factor (a, b, c) should be monotonically decreasing, notice that factor > 'c' is not. > > I could use some help to figure out how to form a logical structure (mostly > just syntax), that will check each 'next value' for each factor to see if it > is less than the previous value. ?If it is less than the previous value, do > nothing, else subtract 'next value' from 'current value', add that amount to > the starting value and each previous value to the 'next value' is greater > than 'previous value'. > > So basically the data.frame would look like: > > a 3 > a 2 > a 1 > b 3 > b 2 > c 3 > c 3 > c 1 > c 1 >-- Sarah Goslee http://www.functionaldiversity.org
try this:> test <- data.frame(A=c("a", "a", "a", "b", "b", "c", "c", "c", "c"), B=c(3,2,1,3,2,2,3,1,1)) > testA B 1 a 3 2 a 2 3 a 1 4 b 3 5 b 2 6 c 2 7 c 3 8 c 1 9 c 1> # determine which group is not decreasing > tapply(test$B, test$A, function(x) any(diff(x) > 0))a b c FALSE FALSE TRUE>On Sun, Jun 19, 2011 at 4:20 PM, Christopher Peters <cpeter9 at lsu.edu> wrote:> I have a data.frame as follows: > > a ?3 > a ?2 > a ?1 > b ?3 > b ?2 > c ?2 > c ?3 > c ?1 > c ?1 > > Each factor (a, b, c) should be monotonically decreasing, notice that factor > 'c' is not. > > I could use some help to figure out how to form a logical structure (mostly > just syntax), that will check each 'next value' for each factor to see if it > is less than the previous value. ?If it is less than the previous value, do > nothing, else subtract 'next value' from 'current value', add that amount to > the starting value and each previous value to the 'next value' is greater > than 'previous value'. > > So basically the data.frame would look like: > > a 3 > a 2 > a 1 > b 3 > b 2 > c 3 > c 3 > c 1 > c 1 > > Thanks for your help! > __________________________________ > Christopher P. Peters > Research Associate > Center for Energy Studies > http://www.enrg.lsu.edu/staff/peters > Energy, Coast & Environment Building > Louisiana State University > Baton Rouge, LA 70803 > Telephone: 225-578-4400 > Fax: 225-578-4541 > > ? ? ? ?[[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Jim Holtman Data Munger Guru What is the problem that you are trying to solve?
If I understand you correctly, you are trying to find the cumulative maximum from the end within each level of the factor. If this is what you are trying to do, then here is one way you might like to do it. First, define the function:> cumMax <- function(x) Reduce(max, x, right = TRUE, accumulate = TRUE)Here is how you might use it:> testA B 1 a 3 2 a 2 3 a 1 4 b 3 5 b 2 6 c 2 7 c 3 8 c 1 9 c 1> (test <- within(test, B <- ave(B, A, FUN = cumMax))A B 1 a 3 2 a 2 3 a 1 4 b 3 5 b 2 6 c 3 7 c 3 8 c 1 9 c 1 -----Original Message----- From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Christopher Peters Sent: Monday, 20 June 2011 6:21 AM To: r-help at r-project.org Subject: [R] For loop by factor. I have a data.frame as follows: a 3 a 2 a 1 b 3 b 2 c 2 c 3 c 1 c 1 Each factor (a, b, c) should be monotonically decreasing, notice that factor 'c' is not. I could use some help to figure out how to form a logical structure (mostly just syntax), that will check each 'next value' for each factor to see if it is less than the previous value. If it is less than the previous value, do nothing, else subtract 'next value' from 'current value', add that amount to the starting value and each previous value to the 'next value' is greater than 'previous value'. So basically the data.frame would look like: a 3 a 2 a 1 b 3 b 2 c 3 c 3 c 1 c 1 Thanks for your help! __________________________________ Christopher P. Peters Research Associate Center for Energy Studies http://www.enrg.lsu.edu/staff/peters Energy, Coast & Environment Building Louisiana State University Baton Rouge, LA 70803 Telephone: 225-578-4400 Fax: 225-578-4541 [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Chris, This doesn't cover all possible cases, but does work for your example. It should be enough for you to tweak for your actual data. diffsum <- function(x) { # first identify the decreasing values # and the difference between increasing values xdif <- x[2:length(x)] - x[1:(length(x)-1)] xdif <- c(xdif, 0) # last element has nothing to compare to xdif[xdif <= 0] <- 0 # then figure out what to add # NOTE: your example is not clear on what to do if # there's a gap followed by more increasing number xsum <- rev(cumsum(rev(xdif))) xsum[xdif == 0] <- 0 x + xsum } diffsum(c(2,3,5,2,1)) test <- data.frame(A=c("a", "a", "a", "b", "b", "c", "c", "c", "c"), B=c(3,2,1,3,2,2,3,1,1)) test2 <- lapply(split(test$B, test$A), diffsum) test3 <- data.frame(A=rep(names(test2), times=lapply(test2, length)), B=unlist(test2)) Sarah On Mon, Jun 20, 2011 at 9:51 AM, Christopher Peters <cpeter9 at lsu.edu> wrote:> Sarah, ?thank you this is very close. > The difference is that I'm not trying to sort to make it monotonic, but > rather take the difference between any increasing value in the series and > the previous value and add that difference back into each previous value. > For example. > column ? var1 ? ?diff (0 where decreasing) ? ?var2 (<--correct) > a ? ? ? ? ? ? 2 ? ? ? ?1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5 <- (2 + > (1+2)) > a ? ? ? ? ? ? 3 ? ? ? ?2 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5 <- (3 + (2)) > a ? ? ? ? ? ? 5 ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5 > a ? ? ? ? ? ? 2 ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2 > a ? ? ? ? ? ? 1 ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1 > Chris > ______________________ > > > On Sun, Jun 19, 2011 at 6:02 PM, Sarah Goslee <sarah.goslee at gmail.com> > wrote: >> >> This works, but I'm still hunting for a more elegant final step: >> > test <- data.frame(A=c("a", "a", "a", "b", "b", "c", "c", "c", "c"), >> > B=c(3,2,1,3,2,2,3,1,1)) >> > test2 <- lapply(split(test$B, test$A), sort, dec=TRUE) >> > test3 <- data.frame(A=rep(names(test2), times=lapply(test2, length)), >> > B=unlist(test2)) >> >> It will also group data by factor, which was already done in your example. >> >> Sarah >> >> On Sun, Jun 19, 2011 at 4:20 PM, Christopher Peters <cpeter9 at lsu.edu> >> wrote: >> > I have a data.frame as follows: >> > >> > a ?3 >> > a ?2 >> > a ?1 >> > b ?3 >> > b ?2 >> > c ?2 >> > c ?3 >> > c ?1 >> > c ?1 >> > >> > Each factor (a, b, c) should be monotonically decreasing, notice that >> > factor >> > 'c' is not. >> > >> > I could use some help to figure out how to form a logical structure >> > (mostly >> > just syntax), that will check each 'next value' for each factor to see >> > if it >> > is less than the previous value. ?If it is less than the previous value, >> > do >> > nothing, else subtract 'next value' from 'current value', add that >> > amount to >> > the starting value and each previous value to the 'next value' is >> > greater >> > than 'previous value'. >> > >> > So basically the data.frame would look like: >> > >> > a 3 >> > a 2 >> > a 1 >> > b 3 >> > b 2 >> > c 3 >> > c 3 >> > c 1 >> > c 1 >> > >> ---- Sarah Goslee http://www.functionaldiversity.org