Search code examples
rmatrixcrosstabsummaryxtable

Restructuring and creating a 5 x 5 summary matrix r


I have a dataset with three columns

The first column is ID

The second column is Intervention with two levels : Pre, Post

The third column is Response with 5 levels : strongly disagree, disagree, neutral, agree, strongly agree

  RecordId  Intervention          Response
  26        Post                  neutral
  26        Pre                   agree
  27        Post                  Strongly Agree
  27        Pre                   strongly disagree
  29        Post                  neutral
  .         .                     .
  .         .                     .
  .         .                     .

The actual dataset is below

    df <- structure(list(record_id = c(26, 26, 27, 27, 29, 29, 30, 30, 
33, 33, 34, 34, 36, 36, 39, 39, 40, 40, 42, 42, 44, 44, 45, 45, 
46, 46, 49, 49, 50, 50, 52, 52, 53, 53, 55, 55), Intervention = c("Post", 
"Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre", 
"Post", "Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre", "Post", 
"Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre", 
"Post", "Pre", "Post", "Pre", "Post", "Pre", "Post", "Pre"), 
    Response = structure(c(3L, 4L, 5L, 1L, 3L, 5L, 5L, 5L, 4L, 
    5L, 3L, 2L, 4L, 4L, 4L, 5L, 2L, 5L, 4L, 4L, 3L, 4L, 1L, 1L, 
    2L, 5L, 2L, 2L, 5L, 5L, 4L, 4L, 4L, 4L, 3L, 4L), .Label = c("strongly disagree", 
    "disagree", "neutral", "agree", "strongly agree"), class = c("labelled", 
    "factor"), label = "")), .Names = c("record_id", "Intervention", 
"Response"), row.names = c(1L, 2L, 3L, 4L, 6L, 7L, 8L, 9L, 12L, 
13L, 14L, 15L, 17L, 18L, 21L, 22L, 23L, 24L, 26L, 27L, 29L, 30L, 
31L, 32L, 33L, 34L, 37L, 38L, 39L, 40L, 42L, 43L, 44L, 45L, 47L, 
48L), class = "data.frame")

How do I convert this to a 5 x 5 matrix like this below

                  Post
Pre               StronglyAgree   Agree Neutral  Disagree StronglyDisagree  
StronglyAgree     ---            ---   ---      ---        ---      
Agree             ---            ---   ---      ---      ---
Neutral           ---            ---   ---      ---      ---
Disagree          ---            ---   ---      ---      ---
StronglyDisagree  ---            ---   ---      ---      ---

Solution

  • If I understand you correctly, this may work:

    library(dplyr)
    library(tidyr)
    
    df %>% 
     pivot_wider(record_id, names_from = Intervention, values_from = Response) %>% 
     select(Pre, Post) %>% 
     table()
    
    #              Post
    # Pre                 strongly disagree disagree neutral agree strongly agree
    #  strongly disagree                 1        0       0     0              1
    #  disagree                          0        1       1     0              0
    #  neutral                           0        0       0     0              0
    #  agree                             0        0       3     4              0
    #  strongly agree                    0        2       1     2              2
    

    You can also use spread in the same way:

    df %>%
     spread(Intervention, Response) %>%
     select(Pre, Post) %>%
     table()