r - Extract Values from Statistical Objects in List to Vector

Viewed 208

I have list of statistical objects from which I would like extract p-values.

The question is similar to the results of this function:

ls.stests <- apply(mtcars, 2, shapiro.test)

I would like to end up with is vector resembling (preferably without using a loop, but hey):

0.1229, 6.058e-06, 0.02081...

I have tried the following:

ls.stests[[1:14]$p.value], ls.stests[[, "p.value"]]
2 Answers

It is always better to check the structure before doing any extraction

 str(ls.stests)
List of 11
 $ mpg :List of 4
  ..$ statistic: Named num 0.948
  .. ..- attr(*, "names")= chr "W"
  ..$ p.value  : num 0.123
  ..$ method   : chr "Shapiro-Wilk normality test"
  ..$ data.name: chr "newX[, i]"
  ..- attr(*, "class")= chr "htest"
 $ cyl :List of 4
  ..$ statistic: Named num 0.753
  .. ..- attr(*, "names")= chr "W"
  ..$ p.value  : num 0.00000606
  ..$ method   : chr "Shapiro-Wilk normality test"
  ..$ data.name: chr "newX[, i]"
  ..- attr(*, "class")= chr "htest"
 $ disp:List of 4
...

From the structure, it is evidents that it is a list of list i.e. the outer list is for the columns from the apply and the inner nested list from the output of shapiro.test

So, we loop over the list with one of the *apply functions i.e. sapply, and extract the p.value from the list output of 'shapiro.test'

sapply(ls.stests, function(x) x$p.value)

-output

        mpg              cyl             disp               hp             drat               wt             qsec               vs 
0.12288135853944 0.00000605833813 0.02080656961086 0.04880823810517 0.11006075742668 0.09265498889321 0.59351764929516 0.00000009737376 
              am             gear             carb 
0.00000007836354 0.00001306843765 0.00043824049593 

We may also do this in a single step

apply(mtcars, 2, function(x) shapiro.test(x)$p.value)
             mpg              cyl             disp               hp             drat               wt             qsec               vs 
0.12288135853944 0.00000605833813 0.02080656961086 0.04880823810517 0.11006075742668 0.09265498889321 0.59351764929516 0.00000009737376 
              am             gear             carb 
0.00000007836354 0.00001306843765 0.00043824049593 

Or with dplyr

library(dplyr)
mtcars %>% 
     summarise(across(everything(), ~ shapiro.test(.)$p.value))
#        mpg            cyl       disp         hp      drat         wt      qsec               vs               am          gear         carb
#1 0.1228814 0.000006058338 0.02080657 0.04880824 0.1100608 0.09265499 0.5935176 0.00000009737376 0.00000007836354 0.00001306844 0.0004382405

We could use map_df and tidy():

library(purrr)
map(mtcars, shapiro.test) %>% 
  keep(~ .x$p.value > 0.05) %>% 
  map_df(broom::tidy)

Output:

  statistic p.value method                     
      <dbl>   <dbl> <chr>                      
1     0.948  0.123  Shapiro-Wilk normality test
2     0.946  0.110  Shapiro-Wilk normality test
3     0.943  0.0927 Shapiro-Wilk normality test
4     0.973  0.594  Shapiro-Wilk normality test
Related