Search code examples
rstatisticsfrequency

add marginal frequency to three way frequency table


I want to create a cross frequency table of three (weighted) variables with marginal frequency. Here is a reproducible example

library(stats)
library(dplyr)

data("cms_patient_care", package = "tidyr")
weights <- rnorm(252, 1,0.1)
df <- cbind(cms_patient_care, weights)
crosstabs <- xtabs(weights ~ facility_name + type + measure_abbr, data=df)

Now I'd like to have the marginal frequency of each measure_abbr by facility_name * type

So far, I've managed to have the marginal frequency of the first element of each facility_name*type with this function and addmargins()

marg <- function(x) {x[1]/sum(x)*100} 
crosstabs2 <- addmargins(crosstabs, margin=3, FUN = marg)

How can I get the rest of it ?


Solution

  • In case someone is looking to do the same, I've dropped the idea of using addmargins() because the output has to be the same dimension as stated in margin, so in order for it to work, you'd need to do the following, which is really unuseful

    marg <- function(x) {x[1]/sum(x)*100} 
    marg2 <- function(x) {x[2]/sum(x)*100} 
    marg3 <- function(x) {x[3]/sum(x)*100} 
    ...
    crosstabs2 <- addmargins(crosstabs, margin=c(3,3,3,...), FUN = c(marg, marg2, marg3,...))
    

    I've managed to do the same using a small function:

    • data is the output of xtabs
    • variable_name is the name of the variable (between quotation marks) you want the marginal frequency of (in the example : "measure_abbr"). Note that I use position to select variables.
    freq_marg <- function(data, variable_name){
      df <- as.data.frame(data) %>%  
        group_by(across(1:which(colnames(.) == variable_name) - 1)) %>%
        mutate(Somme_Freq = sum(Freq)) %>%
        ungroup() %>%
        mutate(RowPercent = Freq / Somme_Freq)
      return(df)
    }
    crosstabs2 <- freq_marg(crosstabs,"measure_abbr")