Home > Net >  R: List of multiple svytables to data frames
R: List of multiple svytables to data frames

Time:06-22

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?

CodePudding user response:

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

  • Related