Reputation: 351
I would like to do a rowsum (acumulate) per column in the same row. What I spect is something lik this:
test = data.frame(c(0,1,1,1,0,0),c(0,0,1,1,1,0),c(0,0,0,1,1,1),c(0,0,0,0,1,1),c(0,0,0,0,0,1))
colnames(test) = c('Position','Position1','Position2','Position3','Position4')
> test
Position Position1 Position2 Position3 Position4
1 0 0 0 0 0
2 1 0 0 0 0
3 1 1 0 0 0
4 1 1 1 0 0
5 0 1 1 1 0
6 0 0 1 1 1
result = data.frame(c(0,1,2,3,0,0),c(0,0,1,2,3,0),c(0,0,0,1,2,3),c(0,0,0,0,1,2),c(0,0,0,0,0,1))
colnames(result) = c('Position','Position1','Position2','Position3','Position4')
> result
Position Position1 Position2 Position3 Position4
1 0 0 0 0 0
2 1 0 0 0 0
3 2 1 0 0 0
4 3 2 1 0 0
5 0 3 2 1 0
6 0 0 3 2 1
The data.frame result is what I want.
Thanks
Upvotes: 0
Views: 506
Reputation: 11480
As a similar alternative to @duckmayr
apply(test, 2, function(x) {x[x] <- 1:sum(x); x})
# Position Position1 Position2 Position3 Position4
#[1,] 0 0 0 0 0
#[2,] 1 0 0 0 0
#[3,] 2 1 0 0 0
#[4,] 3 2 1 0 0
#[5,] 0 3 2 1 0
#[6,] 0 0 3 2 1
further detail:
{
x[x] <- # this is a special case because you want to replace the ones. 1 = TRUE in R internally. So you assign values where x == 1. More general would be to write x[x == 1]
1:sum(x) # 1:N makes a sequence from 1, 2, 3, ..., N. sum(x) will return the amount of ones in a col. Again, more general would be `sum(x == 1)`.
; x # This part is similar to return(x), We want to return the changes we made in x.
}
Upvotes: 1
Reputation: 16910
At first I thought you just needed to apply cumsum()
to each column, but it appears you also need to multiply the cumulative sum by the columns themselves to ensure the zeros are preserved:
test = data.frame(c(0,1,1,1,0,0),c(0,0,1,1,1,0),c(0,0,0,1,1,1),c(0,0,0,0,1,1),c(0,0,0,0,0,1))
colnames(test) = c('Position','Position1','Position2','Position3','Position4')
apply(test, 2, function(x) x * cumsum(x))
#> Position Position1 Position2 Position3 Position4
#> [1,] 0 0 0 0 0
#> [2,] 1 0 0 0 0
#> [3,] 2 1 0 0 0
#> [4,] 3 2 1 0 0
#> [5,] 0 3 2 1 0
#> [6,] 0 0 3 2 1
Created on 2018-11-19 by the reprex package (v0.2.1)
If you truly just want a cumulative sum for each column, you can just use apply(df, 2, cumsum)
:
test = data.frame(c(0,1,1,1,0,0),c(0,0,1,1,1,0),c(0,0,0,1,1,1),c(0,0,0,0,1,1),c(0,0,0,0,0,1))
colnames(test) = c('Position','Position1','Position2','Position3','Position4')
apply(test, 2, cumsum)
#> Position Position1 Position2 Position3 Position4
#> [1,] 0 0 0 0 0
#> [2,] 1 0 0 0 0
#> [3,] 2 1 0 0 0
#> [4,] 3 2 1 0 0
#> [5,] 3 3 2 1 0
#> [6,] 3 3 3 2 1
Created on 2018-11-19 by the reprex package (v0.2.1)
Upvotes: 2