grig109
grig109

Reputation: 73

How to add value to previous row if condition is met

What I am trying to do is if a row in column b is equal to 2 then I want to add 3 to the value of the previous row in column a. And if the condition is not met, then I don't want the previous row value to change. When I try this code however R is adding to the subsequent row. And it doesn't matter what I replace the -1 row reference with it always adds to the subsequent row.

df$a[-1] <- ifelse(df$b == 2, df$a[-1] + 3, df$a[-1])

Have                               Want
a b                                a b
0 1                                0 1
1 3                                4 3
2 2                                2 2
2 4                                2 4
4 5                                4 5

Upvotes: 5

Views: 7463

Answers (2)

hodgenovice
hodgenovice

Reputation: 624

One solution:

I'd find it easiest just to work with the vectors directly, like so:

df$a <- df$a + c((df$b[-1] == 2) * 3, 0)

The issue with your code:

You're getting the subsequent row in your statement because each element of the first argument, df$b==2 matches to the next row of df$a. Let's look at the example in your question to illustrate:

df <- data.frame(a=c(0,1,2,2,4), b=c(1,3,2,4,5))  # As in your question

Here, df$b==2 is equivalent to c(FALSE, FALSE, TRUE, FALSE, FALSE).

df$a[-1] is all the elements of df$a, except the first i.e. equivalent to c(1,2,2,4). Because the argument lengths differ, the first element of df$a[-1] is repeated / looped, like c(1,2,2,4,1).

Therefore, in your statement, the first element of df$b==2 is matched to the first element of df$a[-1], or the second element of df$a (i.e. the subsequent row), and the second element of df$b==2 is matched to the third element of df$a etc.

In this example, your code would give the following output:

ifelse(df$b==2, df$a[-1]+3, df$a[-1])
# Output: 1 2 5 4 1

A way to adjust your code:

Because you want to compare the second element of df$b to the first of df$a and so on, you could adjust your code as follows:

df$a[-nrow(df)] <- ifelse(df$b[-1]==2, df$a+3, df$a)

If any of my explanations are unclear, feel free to comment and I'll try to help!

Upvotes: 3

dimitris_ps
dimitris_ps

Reputation: 5951

Another approach

df <- data.frame(a=c(0, 1, 2, 2, 3),
             b=c(1, 3, 2, 4, 4))

df$a[c(df$b[-1], 0) == 2] <- df$a[c(df$b[-1], 0) == 2] + 3

Upvotes: 5

Related Questions