Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate maximum of next 3 rows of a particular column in each row in R

Tags:

r

I want to create a column "Y" which gives the maximum of the next 3 rows of a particular column "X" in each row in R.

e.g-

X  Y
1  4 (4=max(2,3,4))
2  7 (7= max(3,4,7))
3  9 (9=max(4,7,9))
4
7
9
2
4

Can anyone help with this?

like image 983
snigdha bhardwaj Avatar asked Feb 09 '23 04:02

snigdha bhardwaj


2 Answers

Given:

x <- c(1, 2, 3, 4, 7, 9, 2, 4)

You can look at the embed function:

embed(x, 3)
#      [,1] [,2] [,3]
# [1,]    3    2    1
# [2,]    4    3    2
# [3,]    7    4    3
# [4,]    9    7    4
# [5,]    2    9    7
# [6,]    4    2    9

Note that it's not the right length, and that we're not interested in the first row, so let's make a modification:

embed(c(x[-1], 0, 0, 0), 3)
#      [,1] [,2] [,3]
# [1,]    4    3    2
# [2,]    7    4    3
# [3,]    9    7    4
# [4,]    2    9    7
# [5,]    4    2    9
# [6,]    0    4    2
# [7,]    0    0    4
# [8,]    0    0    0

From there, it should be a simple:

apply(embed(c(x[-1], 0, 0, 0), 3), 1, max)
# [1] 4 7 9 9 9 4 4 0

For convenience, as a function:

this_by_n <- function(invec, n = 3, pad_val = NA, FUN = sum) {
  FUN <- match.fun(FUN)
  apply(embed(c(invec[-1], rep(pad_val, n)), n), 1, {
    function(x) if (all(is.na(x))) NA else FUN(x[!is.na(x)])
  })
}

Try it out:

this_by_n(x, 3, NA, mean)
this_by_n(x, 2, NA, max)
this_by_n(x, 4, NA, min)
like image 146
A5C1D2H2I1M1N2O1R2T1 Avatar answered Feb 16 '23 03:02

A5C1D2H2I1M1N2O1R2T1


We can do this with shift from data.table along with pmax.

library(data.table)
do.call(pmax, c(shift(x, 1:3, type='lead'), na.rm=TRUE))
#[1]  4  7  9  9  9  4  4 NA

Similarly, pmin gives the min value per each row

do.call(pmin, c(shift(x, 1:3, type='lead'), na.rm=TRUE))
#[1]  2  3  4  2  2  2  4 NA

Or for mean values, we use

rowMeans(do.call(cbind,shift(x, 1:3, type='lead')), na.rm=TRUE)

data

 x <- c(1, 2, 3, 4, 7, 9, 2, 4)
like image 41
akrun Avatar answered Feb 16 '23 04:02

akrun