Reputation: 55
I am new to programming (i.e., loops and if-else statements), but not new to statistics in R.
I have about 16 traits I want to compare between males and females within 5 different populations, so 5x16 comparisons. I first want to check if the male and female trait variances are equal (var.test) and then use this information to determine the correct version of the t.test function (either var = T or var = F). I am trying to write a loop to automate this process.
I wrote a functioning if-else statement:
if ((var.test(male$mass,female$mass)$p.value < 0.05) == "TRUE") {
t.test(male$mass,female$mass, var = F)
} else
t.test(male$mass,female$mass, var = T)
But I cannot seem to figure out how to apply this to all my traits.
I don't want to use two nested for statements:
for (i in c(male$trait1, male$trait2,...)) {
for (j in c(female$trait1, female$trait2,...)) {
...
}
}
Because this would create a matrix performing var.test and t.test on all combinations of traits. Whereas, I want the male and female version of each trait paired only.
Here is the format of my data. I made two subsets of the data (male and female):
head(male)
id location gens log.gens sex mass head cbl
49 Hawaii 268 2.428135 M 583.86 78.648 65.54
27 Hawaii 268 2.428135 M 692.30 83.604 69.67
33 Hawaii 268 2.428135 M 647.70 81.180 67.65
34 Hawaii 268 2.428135 M 704.70 84.720 70.60
35 Hawaii 268 2.428135 M 604.90 82.440 68.70
Upvotes: 1
Views: 1244
Reputation: 764
I am not sure the format you hope to obtain.
Something like this will return a list
listOfTraits <- c('mass', 'head', 'cbl')
resultList <- lapply(listOfTraits, FUN = function(trait) {
if (var.test(male[[trait]],female[[trait]])$p.value < 0.05) {
t.test(male[[trait]],female[[trait]], var = F)
} else{
t.test(male[[trait]],female[[trait]], var = T)
}
})
Second Fix
listOfTraits <- c('mass', 'head', 'cbl')
resultList <- lapply(listOfTraits, FUN = function(trait) {
if (var.test(male[[trait]],female[[trait]])$p.value < 0.05) {
x <- t.test(male[[trait]],female[[trait]], var = T)
names(x$estimate) <- c(paste0('male_',trait),paste0('female_',trait))
x$data.name <- paste0('male_',trait, " and ",paste0('female_',trait))
} else{
x <- t.test(male[[trait]],female[[trait]], var = T)
names(x$estimate) <- c(paste0('male_',trait),paste0('female_',trait))
x$data.name <- paste0('male_',trait, " and ",paste0('female_',trait))
}
x
})
Upvotes: 1
Reputation: 7312
Take the function and use purrr:map()
or purrr:map2()
which will iterate each value through the function.
Upvotes: 0
Reputation: 216
Sorry if misinterpreted your question, it sounds to me like you are just trying to apply a loop to your first if-else statement so it will cycle through all of the traits, as it did mass? To refer to the column name in the loop you will need to refer to the columns with the general notation: data["numeric row","numeric column"]
instead of data$"column name"
.
#cycles through a vector comprised of 1 through the number of columns of the data (assuming the number of traits for each sex is equal).
for(i in 1:length(male)){
#your if-else, refering to columns with row/column notation.
if ((var.test(male[,i],female[,i])$p.value < 0.05) == "TRUE") {
t.test(male[,i],female[,i], var = F)
} else {
t.test(male[,i],female[,i], var = T)
}
This will apply this if-else to all traits. Note that this will not store the results of the t.test functions.
Upvotes: 0