Search code examples
rlistframesurvey

R: List of multiple svytables to data frames


I have a multiple svytable in list and from that list I want to make them separate dataframes by saving the same data structure.

For example:

library(survey)
data(api)
x <- apiclus1
dclus1 <- svydesign(id=~dnum, weights=~pw, data=x, fpc=~fpc)
n <- c("sch.wide", "cname") 

for(k in seq_along(n)){
  assign((paste0( n[[k]], "_1")),((svytable(as.formula(paste0("~", n[[k]], "+stype")), design = dclus1, na.action=na.pass))))
}

list<- list(sch.wide_1, cname_1) 
result <- lapply(list, function(x) ((prop.table(x, margin =2)*100)))

How to make the separate data frames from result list tables?


Solution

  • Edit: simplified approach modifying your for loop and with the use of janitor package

    for(k in seq_along(n)) {
      assign((paste0(n[[k]], "_1")), ((
        svytable(
          as.formula(paste0("~", n[[k]], "+stype")),
          design = dclus1,
          na.action = na.pass
        ) %>% as.data.frame() %>% 
          pivot_wider(names_from = stype, values_from = Freq) %>%
          adorn_percentages("col") %>% adorn_pct_formatting()
      )))
    }
    

    now you got:

    > sch.wide_1
     sch.wide     E     H     M
           No  8.3% 21.4% 32.0%
          Yes 91.7% 78.6% 68.0%
    > cname_1
           cname     E     H     M
         Alameda  5.6%  7.1%  8.0%
          Fresno  1.4%  7.1%  4.0%
            Kern  0.7%  0.0%  4.0%
     Los Angeles  8.3%  0.0% 12.0%
       Mendocino  1.4%  7.1%  4.0%
          Merced  1.4%  7.1%  4.0%
          Orange  9.0%  0.0% 12.0%
          Plumas  2.8% 28.6%  4.0%
       San Diego 34.7% 14.3% 12.0%
     San Joaquin 20.8% 21.4% 16.0%
     Santa Clara 13.9%  7.1% 20.0%
    

    you can explore janitor package and modify pct formatting, total,... to get your desired output.

    not sure if you're going to do it 1 by one or you need a loop for it: here's one way for getting them separately:

    a <- data.frame(result[1]) %>% 
      pivot_wider(names_from = stype, values_from = Freq)
    
    > a
    # A tibble: 2 × 4
      sch.wide     E     H     M
      <fct>    <dbl> <dbl> <dbl>
    1 No        8.33  21.4    32
    2 Yes      91.7   78.6    68
    
    b <- data.frame(result[2]) %>% 
      pivot_wider(names_from = stype, values_from = Freq)
    
    b
    # A tibble: 11 × 4
       cname            E     H     M
       <fct>        <dbl> <dbl> <dbl>
     1 Alameda      5.56   7.14     8
     2 Fresno       1.39   7.14     4
     3 Kern         0.694  0        4
     4 Los Angeles  8.33   0       12
     5 Mendocino    1.39   7.14     4
     6 Merced       1.39   7.14     4
     7 Orange       9.03   0       12
     8 Plumas       2.78  28.6      4
     9 San Diego   34.7   14.3     12
    10 San Joaquin 20.8   21.4     16
    11 Santa Clara 13.9    7.14    20
    

    want to make a loop for it?

    for (ii in 1:length(result)) {
      assign(
        paste0("df_", ii),
        as.data.frame(result[[ii]]) %>%
          pivot_wider(names_from = stype, values_from = Freq)
      )
      
    }
    

    now you have df_1 and df_2

    > df_1
    # A tibble: 2 × 4
      sch.wide     E     H     M
      <fct>    <dbl> <dbl> <dbl>
    1 No        8.33  21.4    32
    2 Yes      91.7   78.6    68
    > df_2
    # A tibble: 11 × 4
       cname            E     H     M
       <fct>        <dbl> <dbl> <dbl>
     1 Alameda      5.56   7.14     8
     2 Fresno       1.39   7.14     4
     3 Kern         0.694  0        4
     4 Los Angeles  8.33   0       12
     5 Mendocino    1.39   7.14     4
     6 Merced       1.39   7.14     4
     7 Orange       9.03   0       12
     8 Plumas       2.78  28.6      4
     9 San Diego   34.7   14.3     12
    10 San Joaquin 20.8   21.4     16
    11 Santa Clara 13.9    7.14    20
    

    there might be a shortcut for it but this is how I'm doing so far. good luck