1

I have recently started writing custom R function but got stuck with some problems. I have the following dat data frame.

Test data

G<- c(1, 1, 1, 1, 2, 2, 2, 2) # Gender 1= male, 2= female
A<- c(24.5, 25.5, 26.5, 27.5, 24.5, 25.5, 26.5, 27.5) # Age in month
b85<- c(17.00, 17.90, 18.20, 18.50, 17.50, 19.00, 19.40, 20.00) # BMI 85 percentile
b95 <- c(18.8, 17.2, 18.46, 17.91, 18.76, 17.10, 17.28, 18.01) # BMI 95 percentile
b97 <- c(19.89, 19.52, 18.84, 20.87, 18.33, 19.59, 19.63, 17.74) # BMI 97 percentile
dat<- data.frame(G, A, b85, b95, b97)

I want to write a R function that will take Gender, age as argument and based on input for sex the data will subset into a new data containing only male or female. After that I will evaluate some expression on the new data inside the function.

Function

I have tried the following

tstfun <- function(data, age, sex= c(1,2), pctile){
  dat_sex <- data[which(data$G == sex), ] # Suppose to give me a data for male or female only.

  abs_deviance <- abs(dat_sex$A - age)
  abs_deviance
  
  # later there will be 
  # more complex expression to evaluate 
  # based on the dat_sex data
  
}

tstfun(data = dat, age = 25.6, sex = 2)

No matter which gender I choose it alwayes gives me absolute distance of age from A for the first four observations. I don't know what' going on. I would appericiate any kind of suggestion.

Note

As you might already understand that I am a novice function writer. If anyone can suggest to me some books or online materials to improve my skills like how to write functions efficiently, and how to generalize them, that would be really helpful.

Thanks!

Addition

Maybe I am missing something!

tstfun <- function(data, age, sex= c(1,2), pctile){
  dat_sex <- data[which(data$G == sex), ] # Suppose to give me a data for male or female only.

  abs_deviance <- abs(dat_sex$A - age)
  abs_deviance
  
  i_1stmin <- which.min(abs_deviance)
  i_2ndmin<- which(abs_deviance==sort(abs_deviance, decreasing = F)[2])
  
  xcord <- c(dat_sex$A[i_1stmin], dat_sex$A[i_2ndmin])
  ycord <- with(dat_sex, c(pctile[i_1stmin], pctile[i_2ndmin]))
  
  L<- list(abs_deviance, c(i_1stmin, i_2ndmin), xcord, ycord )
  return(L)
  
}

tstfun(data = dat, age = 25.6, sex = 2, pctile = b95)

This should give me 17.10, 17.28 as ycord.

  • 1
    Well... it gives the same result because it should! A is identical for gender 1 and 2. – user2974951 Jun 28 '22 at 07:01
  • As mentioned above, I think your function is doing what it should and the expected result is identical for both genders. Check it out if you change you A variable to `A<- c(24.5, 25.5, 26.5, 27.5, 24.5, 25.5, 26.5, 45.5) # Age in month` – VvdL Jun 28 '22 at 07:03
  • I got your point. However, kindly check the updated question. Thank you! – user11760503 Jun 28 '22 at 07:29

1 Answers1

0

Here I find for myself two possible solutions. All of them require to use additional packages - dplyr.

Option 1:

tstfun <- function(data, age, sex= c("1", "2"), pctile){
  
  sex <- match.arg(sex)
  
  if (sex == 1){
    
    dat_sex <- dplyr::filter(data, sex == 1)
    # code...
  } else {
    
    dat_sex <- dplyr::filter(data, sex == 2)
    # code...
    
  }
  
}

Option 2, less complex:

tstfun <- function(data, age, sex_var = c(1,2), pctile){
 
  dat_sex <- data %>% filter(sex == sex_var)
  
  # code...
} 
rg4s
  • 811
  • 5
  • 22
  • Thank you so much for your comment. However, I tried option 2 but got deviances for all 8 observations. – user11760503 Jun 28 '22 at 07:16
  • tstfun <- function(data, age, sex_var = c(1,2), pctile){ dat_sex <- data %>% filter(G == sex_var) abs_deviance <- abs(dat_sex$A - age) abs_deviance } tstfun(data = dat, age = 25.6, sex_var = 1) – user11760503 Jun 28 '22 at 07:16