Home > database >  How can I conditionally subset a data frame using a function in R?
How can I conditionally subset a data frame using a function in R?

Time:10-19

i have a data frame that look like this :

a b
1 1
2 2
3 3
4 4
5 5

i want to implement the following slicing:

if the window is 2 that means i have to take the first 2 elements of column a and the last 2 elements of columns b. Sum them and take the minimum of them (which i have done it). For example in the data frame above it must be

a b result
1 4 5
2 5 7

and will report 5.

But (and this is the problem) when the window equals the number of rows of the data frame then i want to take the first element of column a and the last element of column b and just sum them. In my data frame that would be 1 5 = 6.

My effort is this but i dont know how to insert this if else in the function

library(tidyverse)
a = seq(1,5,1)
b = seq(1,5,1)
w = tibble(a,b);w
w[1,1] w[nrow(w),2]

im = function(mat,window){
  
  if(window == nrow(mat))
    mat[1,1]   mat[nrow(mat),2]
  else
    SA = mat%>%
      dplyr::select(1)%>%
      dplyr::slice_head(n=window)
  
    SB = mat%>%
      dplyr::dplyr::select(2)%>%
      dplyr::slice_tail(n=window)
      margin = min(SA SB)
  
      return(margin)
  }
im(w,5)

to test it let's say that i have a vector or windows

vec = seq(1,5,1)

i want to run this function im that i have created for all the elements in the vector vec.

How can i do them in R ? Any help

CodePudding user response:

You can do it with a bunch of if/else:

f <- function(n, data){
  if(n == 1){
    data.frame(a = head(data[1], n), 
               b = head(data[2], n)) |>
      transform(result = a   b)
  }
  else{
    if(n == nrow(data)) n <- 1
    data.frame(a = head(data[1], n), 
               b = tail(data[2], n)) |>
      transform(result = a   b)
  }
}

output

lapply(vec, f, data = w)

[[1]]
  a b result
1 1 1      2

[[2]]
  a b result
1 1 4      5
2 2 5      7

[[3]]
  a b result
1 1 3      4
2 2 4      6
3 3 5      8

[[4]]
  a b result
1 1 2      3
2 2 3      5
3 3 4      7
4 4 5      9

[[5]]
  a b result
1 1 5      6

CodePudding user response:

You can use ifelse function , it always simplify things for me more than if else instruction. Try this it will works :

library(tidyverse)
a = seq(1,5,1)
b = seq(1,5,1)
w = tibble(a,b)

im = function(mat,window){
   
   
   SA = unlist(#unlist to transform list type result of ifelse to vector
      ifelse(
              # here is the condition
         window==nrow(mat),
              # if condition is TRUE return first element
               mat%>%
                  dplyr::select(1)%>%
                  dplyr::slice_head(n=1),
             # if condition is FALSE return first window elements
               mat%>%
         dplyr::select(1)%>%
         dplyr::slice_head(n=window))
         
         )

   
   SB = unlist(
      ifelse(window==nrow(mat),
                      mat%>%
                         dplyr::select(2)%>%
                         dplyr::slice_tail(n=1),
                      mat%>%
                         dplyr::select(2)%>%
                         dplyr::slice_tail(n=window))
      )
   
   margin = min(SA SB)
   
   return(margin)
}


im(w,5)

  • Related