[R] For loop by factor.

Sarah Goslee sarah.goslee at gmail.com
Mon Jun 20 16:14:28 CEST 2011


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



More information about the R-help mailing list