This type of problems generally has to do with reshaping the data. The format should be the long format and the data is in wide format. See this post on how to reshape the data from wide to long format.
The following code reshapes the data, pipes to na.omit
, then split/lapply/combine and put the results in a data.frame format.
a <- c("A", "A", "A", "A", "B", "B","B", "B")
b <- c(11, 9, 4, 1, NA, 2,3,4)
c <- c(2,3, NA, NA, 25, 4, NA, 2)
d <- c(4,5, 3, NA, NA, 2,NA,NA)
df <- data.frame(a, b,c,d)
colnames(df) <- c("Letter", "num1", "num2", "num3")
faux <- function(x){
e <- effsize::cohen.d(value ~ Letter, data = x)
e2 <- unclass(e)
c(e2[1:4],
lower = unname(e2$conf.int[1]),
upper = unname(e2$conf.int[2]),
e2[6:8])
}
long <- reshape2::melt(df, id.vars = "Letter") |> na.omit()
res <- lapply(split(long, long$variable), faux)
do.call(rbind.data.frame, res)
#> method name estimate sd lower upper var conf.level magnitude
#> num1 Cohen's d d 0.9031263 3.598611 -1.155897 2.962150 0.6415931 0.95 large
#> num2 Cohen's d d -0.7524094 10.410998 -3.754631 2.249812 0.8899453 0.95 medium
#> num3 Cohen's d d NA NA NA NA NA 0.95 <NA>
Created on 2022-07-28 by the reprex package (v2.0.1)
Edit
To run the code above as a for
loop, assign the result of split
, explicitly create a results vector and call faux
(auxiliary function) in the loop.
sp <- split(long, long$variable)
res <- vector("list", length = length(sp))
for(i in seq_along(sp)) {
res[[i]] <- faux(sp[[i]])
}
do.call(rbind.data.frame, res)
#> method name estimate sd lower upper var conf.level magnitude
#> 1 Cohen's d d 0.9031263 3.598611 -1.155897 2.962150 0.6415931 0.95 large
#> 2 Cohen's d d -0.7524094 10.410998 -3.754631 2.249812 0.8899453 0.95 medium
#> 3 Cohen's d d NA NA NA NA NA 0.95 <NA>
Created on 2022-07-28 by the reprex package (v2.0.1)