Configural Frequency Analysis Tutorial

Overview

This tutorial provides R code on conducting configural frequency analysis (Lienert & Krauth, 1975; Stemmler, 2020; von Eye, 1990). In brief, configural frequency analysis is similar to a chi-square test in that it uses a contingency table to determine whether instances are evenly distributed across categories. Beyond a chi-square test, however, configural frequency analysis identifies whether particular cells within a contingency table are over- or under-represented.

In this example, we use configural frequency analysis to examine the use of specific turn transitions during a subset (N = 59) of conversations between strangers in which one dyad member disclosed about a current problem. Each turn in the conversations between stranger dyads was coded (e.g., as an acknowledgement, question, hedged disclosure, etc.; see Bodie et al., 2021 in the Journal of Language and Social Psychology for more details about the creation of the turn typology) and the transitions between turn types was tallied across the entire sample. We use configural frequency analysis to determine which turn transitions occur more or less frequently than expected during these conversations.

We also add a third hypothetical variable to illustrate the value of configural frequency analysis for examining more than two variables at a time. Specifically, we add a hypothetical “condition” variable that represents an experimental manipulation in which dyads were assigned to communicate face-to-face or using computer-mediated communication. We include this hypothetical scenario following our initial demonstration of how configural frequency analysis was used in the Bodie et al. (2021) paper.

Note that the accompanying “ConfiguralFrequency_Tutorial_2023June16.rmd” file contains all of the code presented in this tutorial and can be opened in RStudio (a somewhat more friendly user interface to R).

Outline

In this tutorial, we’ll cover…

  • Reading in the data and loading needed packages.
  • Plotting two dyads’ conversation.
  • Preparing the data for configural frequency analysis.
  • Conducting configural frequency analysis.
  • Adding a hypothetical experimental condition to the data.
  • Conducting configural frequency analysis with three variables.

Read in the data and load needed libraries.

Let’s read the data into R.

The data set we are working with is called “StrangerConversations_N59” and is stored as a .csv file (comma-separated values file, which can be created by saving an Excel file as a csv document) on my computer’s desktop.

# Set working directory (i.e., where your data file is stored)
# This can be done by going to the top bar of RStudio and selecting 
# "Session" --> "Set Working Directory" --> "Choose Directory" --> 
# finding the location of your file
setwd("~/Desktop") # Note: You can skip this line if you have 
#the data file and this .rmd file stored in the same directory

# Read in the data
data <- read.csv(file = "StrangerConversations_N59.csv", head = TRUE, sep = ",")

# View the first 10 rows of the data
head(data, 10)
##     id turn role       turn_type
## 1  105    1    1        Question
## 2  105    2    2 Acknowledgement
## 3  105    3    1     Elaboration
## 4  105    4    2 Acknowledgement
## 5  105    5    1     Elaboration
## 6  105    6    2 Acknowledgement
## 7  105    7    1     Elaboration
## 8  105    8    2     Elaboration
## 9  105    9    1     Elaboration
## 10 105   10    2      Reflection

In the data, we can see each row contains information for one turn and there are multiple rows (i.e., turns) for each dyad. Specifically, there is a column for:

  • Dyad ID (id)
  • Time variable - in this case, turn in the conversation (turn)
  • Dyad member ID - in this case, role in the conversation (role; discloser = 1, listener = 2)
  • Turn type - in this case, based upon a typology derived in Bodie et al. (2021; turn_type)

Load the R packages we need.

Packages in R are a collection of functions (and their documentation/explanations) that enable us to conduct particular tasks, such as plotting or fitting a statistical model.

# install.packages(data.table) # Install package if you have never used it before
library(data.table) # For data management: counting turn transitions

# install.packages("devtools") # Install package if you have never used it before
require(devtools) # For version control

#install.packages("confreq") # Install package if you have never used it before
library(confreq) # For conducting configural frequency analysis

# install.packages("dplyr") # Install package if you have never used it before
library(dplyr) # For data management

# install.packages("ggplot2") # Install package if you have never used it before
library(ggplot2) # For plotting

# install.packages("tidyverse")
library(tidyverse) # For data management

Plot Two Dyads’ Conversation.

To get a better feel for the conversation data, let’s plot two dyads’ conversations.

Before creating the plots, it is helpful to set the colors for each turn type so the color of the turn categories are consistent across plots (i.e., the number of turn types present in a given conversation does not affect the color of the turn types). We do this by creating a vector “cols” that contains color assignments (via hex code: https://www.color-hex.com/) for each turn type.

A note on accessibility: To make your plots accessible, you may consider adopting a colorblind-friendly palette. David Nichols’ website (https://davidmathlogic.com/colorblind/) provides a great explainer on this issue, as well as a color picking tool.

cols <- c("Elaboration" = "#00BA38", 
          "Question" = "#619CFF", 
          "Acknowledgement" = "#F8766D", 
          "Reflection" = "#DB72FB", 
          "Advice" = "#93AA00",
          "HedgedDisclosure" = "#00C19F")

We’ll create the dyadic categorical time series plot for each exemplar dyad and save these plots to the objects “dyad105_plot” and “dyad123_plot”.

Dyad 105 plot.

# First partition data of interest
dyad105 <- data[data$id == 105, ]

dyad105_plot <-
  # Choose the data, set time variable (turn) for the x-axis 
  ggplot(dyad105, aes(x = turn)) +
  
  # Create title for plot by combining "Dyad = " with the dyad id variable (id)
          ggtitle(paste("Dyad =", unique(dyad105$id))) +
  
  # Create bars for the form of the listeners' turns
          # Partition data for listeners (role = 2)
          geom_rect(data = dyad105[dyad105$role == 2, ], 
                    # Set the width of each bar as -0.5 and +0.5 the value of the time variable (turn)
                    mapping = aes(xmin = turn-.5, xmax = turn+.5, 
                    # Set the height of each bar to range from 0 to 5
                                  ymin = 0, ymax = 5, 
                    # Set the color of each bar to correspond to each turn type
                                  fill = turn_type)) +
  
  # Add a horizontal line to separate bars
          geom_hline(yintercept = 5, color = "black") +
  
  # Create bars for the form of the disclosers' turns
          # Partition data for disclosers (role = 1)
          geom_rect(data = dyad105[dyad105$role == 1, ],
                    # Set the width of each bar as -0.5 and +0.5 the value of the time variable (turn)
                    mapping = aes(xmin = turn-.5, xmax = turn+.5, 
                    # Set the height of each bar to range from 5 to 10
                                  ymin = 5, ymax = 10,
                    # Set the color of each bar to correspond to each turn type
                                  fill = turn_type)) +
  
  # Set color of turn types to vector we created earlier ("cols")
          scale_fill_manual(values = cols) +
  
  # Label for x-axis
          xlab("Turn") + 
  
  # Label for y-axis
          ylab("Role") +
  
  # X-axis ticks and labels
          scale_x_continuous(breaks = seq(0, 110, by = 10)) +
  
  # Y-axis ticks and label
          scale_y_continuous(breaks = c(2.5, 7.5), 
                             labels=c("Listener Turn", "Discloser Turn")) +
  
  # Legend label
          labs(fill = "Turn Type") +
  
  # Additional plot aesthetics
          theme(panel.grid.major = element_blank(), 
                panel.grid.minor = element_blank(),
                axis.text=element_text(color = "black"))

Dyad 123 plot.

# First partition data of interest
dyad123 <- data[data$id == 123, ]

dyad123_plot <-
  # Choose the data, set time variable (turn) for the x-axis
  ggplot(dyad123, aes(x = turn)) +
  
  # Create title for plot by combining "Dyad = " with the dyad id variable (id)
          ggtitle(paste("Dyad =", unique(dyad123$id))) +
  
  # Create bars for the form of the listeners' turns
          # Partition data for listeners (role = 2)
          geom_rect(data = dyad123[dyad123$role == 2, ], 
                    # Set the width of each bar as -0.5 and +0.5 the value of the time variable (turn)
                    mapping = aes(xmin = turn-.5, xmax = turn+.5, 
                    # Set the height of each bar to range from 0 to 5
                                  ymin = 0, ymax = 5, 
                    # Set the color of each bar to correspond to each turn type
                                  fill = turn_type)) +
  
  # Add a horizontal line to separate bars
          geom_hline(yintercept = 5, color = "black") +
  
  # Create bars for the form of the disclosers' turns
          # Partition data for disclosers (role = 1)
          geom_rect(data = dyad123[dyad123$role == 1, ],
                    # Set the width of each bar as -0.5 and +0.5 the value of the time variable (turn)
                    mapping = aes(xmin = turn-.5, xmax = turn+.5, 
                    # Set the height of each bar to range from 5 to 10
                                  ymin = 5, ymax = 10,
                    # Set the color of each bar to correspond to each turn type
                                  fill = turn_type)) +
  
  # Set color of turn types to vector we created earlier ("cols")
          scale_fill_manual(values = cols) +
  
  # Label for x-axis
          xlab("Turn") + 
  
  # Label for y-axis
          ylab("Role") +
  
  # X-axis ticks and labels
          scale_x_continuous(breaks = seq(0, 110, by = 10)) +
  
  # Y-axis ticks and label
          scale_y_continuous(breaks = c(2.5, 7.5), 
                             labels=c("Listener Turn", "Discloser Turn")) +
  
  # Legend label
          labs(fill = "Turn Type") +
  
  # Additional plot aesthetics
          theme(panel.grid.major = element_blank(), 
                panel.grid.minor = element_blank(),
                axis.text=element_text(color = "black"))

Print the plots we just created.

print(dyad105_plot)

print(dyad123_plot)

On the x-axis, we have turn in the conversation. On the y-axis, we have the turn type for the disclosers on the top half and the listeners on the bottom half. Each turn category is represented by a different color and the gray bars indicate when a particular dyad member is not speaking. We can see that Dyad 105 had greater back-and-forth exchange during their conversation, as indicated by the greater number of turns. In both dyads, we can see that the disclosers spent many of their turns elaborating on their problem (green) and the listener used a variety of different turn types.

Prepare the Data for Configural Frequency Analysis.

To prepare the conversation data for configural frequency analysis, we must first count the number of transitions between listener –> discloser turns and the number of transitions between discloser –> listener turns.

First, let’s make sure all the data are ordered by turn within each dyad.

# Order data by ID and turn number 
data <- data[order(data$id, data$turn), ]

# View the first 10 rows of the data
head(data, 10)
##      id turn role        turn_type
## 3805  3    1    1      Elaboration
## 3806  3    2    2  Acknowledgement
## 3807  3    3    1 HedgedDisclosure
## 3808  3    4    2  Acknowledgement
## 3809  3    5    1 HedgedDisclosure
## 3810  3    6    2  Acknowledgement
## 3811  3    7    1      Elaboration
## 3812  3    8    2         Question
## 3813  3    9    1      Elaboration
## 3814  3   10    2  Acknowledgement

Second, before calculating the number of turn transitions, we first need to distinguish between listener and discloser turns of the same label (e.g., listener question vs. discloser question) since these are not distinguished in the “turn_type” variable.

data <- # Select data
        data %>%
        # Update "turn_type" variable so that 
        # if the role = 1 (i.e., if it is a discloser turn),
        # then add a "D" in front of turn type, 
        # otherwise add a "L" in front of turn type
        # separate the D (or L) and the turn type with a "_"
        dplyr::mutate(turn_type = paste0(ifelse(role == 1, "D", "L"), "_", turn_type)) %>%
        # Save the data as a data.frame
        as.data.frame()

# View the first 10 rows of the data
head(data, 10)
##      id turn role          turn_type
## 3805  3    1    1      D_Elaboration
## 3806  3    2    2  L_Acknowledgement
## 3807  3    3    1 D_HedgedDisclosure
## 3808  3    4    2  L_Acknowledgement
## 3809  3    5    1 D_HedgedDisclosure
## 3810  3    6    2  L_Acknowledgement
## 3811  3    7    1      D_Elaboration
## 3812  3    8    2         L_Question
## 3813  3    9    1      D_Elaboration
## 3814  3   10    2  L_Acknowledgement

Third, let’s create a lagged “turn_type” variable. This lagged variable will then be combined with the original “turn_type” variable to create a new variable that represents the turn transition.

After running the code, you will see below that the discloser’s first turn is shown as D_Elaboration. On the same line and in the next column, the first lagged turn is represented as NA to represent the fact that the listener did not speak prior to the discloser’s first turn.

# Create a lagged variable
data <- # Select data
        data %>%
        # Select grouping variable, in this case, dyad ID (id)
        dplyr::group_by(id) %>%
        # Create new variable that is a lag of "turn_type"
        dplyr::mutate(lagged_turn_type = lag(turn_type)) %>%
        # Save the data as a data.frame
        as.data.frame()

# View the first 10 rows of the data
head(data, 10)
##    id turn role          turn_type   lagged_turn_type
## 1   3    1    1      D_Elaboration               <NA>
## 2   3    2    2  L_Acknowledgement      D_Elaboration
## 3   3    3    1 D_HedgedDisclosure  L_Acknowledgement
## 4   3    4    2  L_Acknowledgement D_HedgedDisclosure
## 5   3    5    1 D_HedgedDisclosure  L_Acknowledgement
## 6   3    6    2  L_Acknowledgement D_HedgedDisclosure
## 7   3    7    1      D_Elaboration  L_Acknowledgement
## 8   3    8    2         L_Question      D_Elaboration
## 9   3    9    1      D_Elaboration         L_Question
## 10  3   10    2  L_Acknowledgement      D_Elaboration

We next generate a data frame containing transition frequencies through cross-tabulation, and save it to the data frame “data_dt”. Because there are 7 turn types (6 identified and 1 NA) and 2 roles (listener and discloser), there are 14 turn categories in our dataset. Thus, the crosstab table contains 14 * 14 = 196 cells, representing all pairings or combinations of two turns.

# Reformat data frame to data table
data_dt <- data.table::as.data.table(data)

# Count the occurrence of lagged turn and turn pairs
data_counts <- as.data.frame(with(data_dt, table(turn_type, lagged_turn_type)))

# Count the rows in data_counts
nrow(data_counts)
## [1] 196

Of course, not all of the 196 are legitimate turn transitions. Transitions that were at the beginning or end of the conversation and those that involved uncodable turns will need to be removed. In addition, while they exist in the table, D->D and L->L transitions do not occur in our data. We will remove them in the two code chunks below.

# Remove rows in which the lagged turn in the transition contains a _NA
data_counts <- data_counts[ grep("_NA", data_counts$lagged_turn_type, invert = TRUE) , ]

# Remove rows in which the following turn in the transition contains a _NA
data_counts <- data_counts[ grep("_NA", data_counts$turn_type, invert = TRUE) , ]

# Count the rows in data_counts
nrow(data_counts)
## [1] 144

Since we will be examining listener –> discloser and discloser –> listener turn transitions separately, we will create two different data sets that contain the counts of these turn transitions. We will also remove the L->L and D->D transitions at this step.

# Create listener --> discloser transition data set
# Remove all transitions that begin with a discloser turn from data_counts
# by selecting all rows in lagged_turn_type with the discloser tag "D_"
list2disc <- data_counts[ grep("D_", data_counts$lagged_turn_type, invert = TRUE) , ]

# Remove all transitions that end with a listener turn to create the L->D subset
# by selecting all rows in turn_type with the listener tag "L_"
list2disc <- list2disc[ grep("L_", list2disc$turn_type, invert = TRUE) , ]
nrow(list2disc)
## [1] 36
# View the first 10 rows of the data
head(list2disc, 10)
##              turn_type  lagged_turn_type Freq
## 99   D_Acknowledgement L_Acknowledgement   28
## 100           D_Advice L_Acknowledgement    8
## 101      D_Elaboration L_Acknowledgement  767
## 102 D_HedgedDisclosure L_Acknowledgement  156
## 104         D_Question L_Acknowledgement   28
## 105       D_Reflection L_Acknowledgement    3
## 113  D_Acknowledgement          L_Advice   10
## 114           D_Advice          L_Advice    1
## 115      D_Elaboration          L_Advice   31
## 116 D_HedgedDisclosure          L_Advice    5
# Create discloser --> listener transition data set
# Remove all transitions that begin with a listener turn from data_counts
# by selecting all rows in lagged_turn_type with the listener tag "L_"
disc2list <- data_counts[ grep("L_", data_counts$lagged_turn_type, invert = TRUE) , ]

# Remove all transitions that end with a discloser turn to create the D->L subset
# by selecting all rows in turn_type with the discloser tag "D_"
disc2list <- disc2list[ grep("D_", disc2list$turn_type, invert = TRUE) , ]
nrow(disc2list)
## [1] 36
# View the first 10 rows of the data
head(disc2list, 10)
##             turn_type  lagged_turn_type Freq
## 8   L_Acknowledgement D_Acknowledgement   16
## 9            L_Advice D_Acknowledgement    8
## 10      L_Elaboration D_Acknowledgement  119
## 11 L_HedgedDisclosure D_Acknowledgement   33
## 13         L_Question D_Acknowledgement   24
## 14       L_Reflection D_Acknowledgement   46
## 22  L_Acknowledgement          D_Advice   11
## 23           L_Advice          D_Advice    0
## 24      L_Elaboration          D_Advice    5
## 25 L_HedgedDisclosure          D_Advice    0

Given that we are examining the transitions between six listener turn types and six discloser turn types, we should expect each of our data sets to contain 36 rows. These rows represent all possible transitions, including a few transitions that were not observed in our dataset.

Finally, the confreq package requires the data to be organized in a specific way to conduct configural frequency analysis. Specifically, each data set should have three columns that represent (1) the type of lagged turn, (2) the current type of turn, and (3) the frequency of that turn transition. In the first two columns, each turn type needs to be represented by a number instead of a category label. So, we number the categories in alphabetical order (1 = acknowledgement, 2 = advice, 3 = elaboration, 4 = hedged disclosure, 5 = question, 6 = reflection). The code chunk below recodes the turn labels into numbers.

# Recoding variables in listener --> discloser transition data set
list2disc <- # Select data
             list2disc %>%  
             # Recode lagged turn and following turn variables with numbers
             dplyr::mutate(lagged_turn_type = recode(list2disc$lagged_turn_type, 
                                             "L_Acknowledgement" = 1,
                                             "L_Advice" = 2,
                                             "L_Elaboration" = 3,
                                             "L_HedgedDisclosure" = 4,
                                             "L_Question" = 5,
                                             "L_Reflection" = 6),
                           turn_type = recode(list2disc$turn_type, 
                                             "D_Acknowledgement" = 1,
                                             "D_Advice" = 2,
                                             "D_Elaboration" = 3,
                                             "D_HedgedDisclosure" = 4,
                                             "D_Question" = 5,
                                             "D_Reflection" = 6)) %>%
              # Save the data as a data.frame
              as.data.frame()

# Recoding variables in discloser --> listener transition data set
disc2list <- # Select data
             disc2list %>%  
             # Recode lagged turn and following turn variables with numbers
             dplyr::mutate(lagged_turn_type = recode(disc2list$lagged_turn_type, 
                                             "D_Acknowledgement" = 1,
                                             "D_Advice" = 2,
                                             "D_Elaboration" = 3,
                                             "D_HedgedDisclosure" = 4,
                                             "D_Question" = 5,
                                             "D_Reflection" = 6),
                           turn_type = recode(disc2list$turn_type, 
                                             "L_Acknowledgement" = 1,
                                             "L_Advice" = 2,
                                             "L_Elaboration" = 3,
                                             "L_HedgedDisclosure" = 4,
                                             "L_Question" = 5,
                                             "L_Reflection" = 6)) %>%
              # Save the data as a data.frame
              as.data.frame()

Let’s reorder the values of the turn variables since they represent the turn categories in alphabetical order, and reorganize the columns so the lagged turns come first.

# Order data by lagged_turn_type and turn_type for listener --> discloser turn transitions
list2disc <- list2disc[order(list2disc$lagged_turn_type, list2disc$turn_type), ]

# Reorder the columns for listener --> discloser turn transitions
list2disc <- list2disc[, c(2, 1, 3)]

# View the first 10 rows of the data
head(list2disc, 10)
##     lagged_turn_type turn_type Freq
## 99                 1         1   28
## 100                1         2    8
## 101                1         3  767
## 102                1         4  156
## 104                1         5   28
## 105                1         6    3
## 113                2         1   10
## 114                2         2    1
## 115                2         3   31
## 116                2         4    5
# Order data by lagged_turn_type and turn_type for discloser --> listener turn transitions
disc2list <- disc2list[order(disc2list$lagged_turn_type, disc2list$turn_type), ]

# Reorder the columns for discloser --> listener turn transitions
disc2list <- disc2list[, c(2, 1, 3)]

# View the first 10 rows of the data
head(disc2list, 10)
##    lagged_turn_type turn_type Freq
## 8                 1         1   16
## 9                 1         2    8
## 10                1         3  119
## 11                1         4   33
## 13                1         5   24
## 14                1         6   46
## 22                2         1   11
## 23                2         2    0
## 24                2         3    5
## 25                2         4    0

We can also rename the columns to represent the speaker of that turn.

# Rename columns in listener --> discloser turn transition data
colnames(list2disc) <- c("listener", "discloser", "freq")

# Rename columns in discloser --> listener turn transition data
colnames(disc2list) <- c("discloser", "listener", "freq")

Conduct the Configural Frequency Analysis.

Let’s examine the structure of the data sets.

We need to check whether the variables are in the correct format. Specifically, we need the variables that label the turn types of the listeners and disclosers to be factor variables (instead of integer variables). A factor variable makes sure R interprets the variables as categories instead of integers.

# Examine the structure of the listener --> discloser 
# and discloser --> listener data
str(list2disc)
## 'data.frame':    36 obs. of  3 variables:
##  $ listener : num  1 1 1 1 1 1 2 2 2 2 ...
##  $ discloser: num  1 2 3 4 5 6 1 2 3 4 ...
##  $ freq     : int  28 8 767 156 28 3 10 1 31 5 ...
str(disc2list)
## 'data.frame':    36 obs. of  3 variables:
##  $ discloser: num  1 1 1 1 1 1 2 2 2 2 ...
##  $ listener : num  1 2 3 4 5 6 1 2 3 4 ...
##  $ freq     : int  16 8 119 33 24 46 11 0 5 0 ...
# Need the discloser and listener variables to be factors in both datasets
list2disc$listener <- as.factor(list2disc$listener)
list2disc$discloser <- as.factor(list2disc$discloser)

disc2list$listener <- as.factor(disc2list$listener)
disc2list$discloser <- as.factor(disc2list$discloser)

Now that the data are in the correct format, we can run the configural frequency analyses.

Let’s first examine the listener to discloser transitions.

The configural frequency analysis function requires that the data are formatted as a response pattern frequency table.

# Change format of data for configural frequency analysis
# Insert data ("list2disc") in the dat2fre(fre2dat()) function
cfa_list2disc <- dat2fre(fre2dat(list2disc))
## Number of categories for each variable 
##  estimated from data are:  
##  listener discloser 
##  6 6 
##  --> 36 different configurations
# Examine the response pattern frequency table
cfa_list2disc
##    listener discloser Freq
## 1         1         1   28
## 2         1         2    8
## 3         1         3  767
## 4         1         4  156
## 5         1         5   28
## 6         1         6    3
## 7         2         1   10
## 8         2         2    1
## 9         2         3   31
## 10        2         4    5
## 11        2         5    1
## 12        2         6    1
## 13        3         1   98
## 14        3         2    5
## 15        3         3  339
## 16        3         4   42
## 17        3         5   59
## 18        3         6   18
## 19        4         1   43
## 20        4         2    1
## 21        4         3   78
## 22        4         4   17
## 23        4         5    7
## 24        4         6    4
## 25        5         1   14
## 26        5         2    1
## 27        5         3  231
## 28        5         4   23
## 29        5         5    5
## 30        5         6    0
## 31        6         1   52
## 32        6         2    0
## 33        6         3  343
## 34        6         4   44
## 35        6         5   10
## 36        6         6    5

Next, we conduct the configural frequency analysis and save the results. We then examine a summary of the results.

# Conduct configural frequency analysis and save the results
# Insert the response pattern frequency table 
# and the name of the variables of interest (with a ~ and +)
results_list2disc <- CFA(cfa_list2disc, form = "~ listener + discloser") 

# Examine the saved results
summary(results_list2disc , showall = TRUE)
## function Call: 
##  ------------- 
##  Formula: ~ listener + discloser 
##  Variables: listener discloser 
##  Categories: 6 6 
## 
##  results of global tests: 
##  -----------------------
##  pearson Chi-square test: 
##        Chi df pChi alpha
## 1 304.3275 25    0  0.05
## 
##  likelihood ratio test: 
##        Chi df pChi alpha
## 1 294.2896 25    0  0.05
## 
##  Information Criteria: 
##      loglik      AIC      BIC
## 1 -227.0889 476.1777 493.5964
## 
##  results of local tests: 
##  ----------------------- 
##  Type (+) / Antitype (-) based on: z.pChi ; 
##  with Bonferroni adjusted alpha: 0.001388889
##    pat. obs.    exp. Type df  z.Chi z.pChi
## 1   1 1   28  97.881    -  1 -7.063  0.000
## 2   1 2    8   6.392    .  1  0.636  0.262
## 3   1 3  767 714.734    .  1  1.955  0.025
## 4   1 4  156 114.661    +  1  3.861  0.000
## 5   1 5   28  43.947    .  1 -2.406  0.008
## 6   1 6    3  12.385    .  1 -2.667  0.004
## 7   2 1   10   4.845    .  1  2.342  0.010
## 8   2 2    1   0.316    .  1  1.215  0.112
## 9   2 3   31  35.376    .  1 -0.736  0.231
## 10  2 4    5   5.675    .  1 -0.283  0.388
## 11  2 5    1   2.175    .  1 -0.797  0.213
## 12  2 6    1   0.613    .  1  0.494  0.311
## 13  3 1   98  55.466    +  1  5.711  0.000
## 14  3 2    5   3.622    .  1  0.724  0.235
## 15  3 3  339 405.016    -  1 -3.280  0.001
## 16  3 4   42  64.975    .  1 -2.850  0.002
## 17  3 5   59  24.903    +  1  6.833  0.000
## 18  3 6   18   7.018    +  1  4.145  0.000
## 19  4 1   43  14.831    +  1  7.315  0.000
## 20  4 2    1   0.969    .  1  0.032  0.487
## 21  4 3   78 108.293    .  1 -2.911  0.002
## 22  4 4   17  17.373    .  1 -0.089  0.464
## 23  4 5    7   6.659    .  1  0.132  0.447
## 24  4 6    4   1.877    .  1  1.550  0.061
## 25  5 1   14  27.090    .  1 -2.515  0.006
## 26  5 2    1   1.769    .  1 -0.578  0.282
## 27  5 3  231 197.815    .  1  2.359  0.009
## 28  5 4   23  31.734    .  1 -1.550  0.061
## 29  5 5    5  12.163    .  1 -2.054  0.020
## 30  5 6    0   3.428    .  1 -1.851  0.032
## 31  6 1   52  44.887    .  1  1.062  0.144
## 32  6 2    0   2.931    .  1 -1.712  0.043
## 33  6 3  343 327.767    .  1  0.841  0.200
## 34  6 4   44  52.582    .  1 -1.183  0.118
## 35  6 5   10  20.153    .  1 -2.262  0.012
## 36  6 6    5   5.680    .  1 -0.285  0.388

In the results, we can examine the column “Type” to determine which transitions occurred more (+) or less (-) frequently than expected. We can see that the transitions between (1) listener acknowledgements and discloser hedged disclosures, (2) listener elaborations and discloser acknowledgements, (3) listener elaborations and discloser questions, (4) listener elaborations and discloser reflections, and (5) listener hedged disclosures and discloser acknowledgements occurred more frequently than expected. Furthermore, transitions between (1) listener acknowledgements and discloser acknowledgements and (2) listener elaborations and discloser elaborations occurred less frequently than expected.

We next examine the discloser to listener transitions.

The configural frequency analysis function requires that the data are formatted as a response pattern frequency table.

# Change format of data for configural frequency analysis
# Insert data (disc2list) in the dat2fre(fre2dat()) function
cfa_disc2list <- dat2fre(fre2dat(disc2list))
## Number of categories for each variable 
##  estimated from data are:  
##  discloser listener 
##  6 6 
##  --> 36 different configurations
# Examine the response pattern frequency table
cfa_disc2list
##    discloser listener Freq
## 1          1        1   16
## 2          1        2    8
## 3          1        3  119
## 4          1        4   33
## 5          1        5   24
## 6          1        6   46
## 7          2        1   11
## 8          2        2    0
## 9          2        3    5
## 10         2        4    0
## 11         2        5    2
## 12         2        6    0
## 13         3        1  790
## 14         3        2   33
## 15         3        3  329
## 16         3        4   94
## 17         3        5  195
## 18         3        6  361
## 19         4        1  160
## 20         4        2    2
## 21         4        3   33
## 22         4        4   13
## 23         4        5   38
## 24         4        6   44
## 25         5        1   22
## 26         5        2    2
## 27         5        3   71
## 28         5        4   11
## 29         5        5    4
## 30         5        6    2
## 31         6        1    9
## 32         6        2    1
## 33         6        3   14
## 34         6        4    1
## 35         6        5    2
## 36         6        6    3

Next, we conduct the configural frequency analysis and save the results. We then examine a summary of the results.

# Conduct configural frequency analysis and save the results
# Insert the response pattern frequency table 
# and the name of the variables of interest (with a ~ and +)
results_disc2list <- CFA(cfa_disc2list, form = "~ listener + discloser") 

# Examine the saved results
summary(results_disc2list , showall = TRUE)
## function Call: 
##  ------------- 
##  Formula: ~ listener + discloser 
##  Variables: discloser listener 
##  Categories: 6 6 
## 
##  results of global tests: 
##  -----------------------
##  pearson Chi-square test: 
##        Chi df pChi alpha
## 1 365.2749 25    0  0.05
## 
##  likelihood ratio test: 
##        Chi df pChi alpha
## 1 376.1141 25    0  0.05
## 
##  Information Criteria: 
##      loglik      AIC      BIC
## 1 -266.3476 554.6951 572.1139
## 
##  results of local tests: 
##  ----------------------- 
##  Type (+) / Antitype (-) based on: z.pChi ; 
##  with Bonferroni adjusted alpha: 0.001388889
##    pat. obs.    exp. Type df  z.Chi z.pChi
## 1   1 1   16  99.267    -  1 -8.357  0.000
## 2   1 2    8   4.530    .  1  1.630  0.052
## 3   1 3  119  56.231    +  1  8.371  0.000
## 4   1 4   33  14.969    +  1  4.660  0.000
## 5   1 5   24  26.097    .  1 -0.410  0.341
## 6   1 6   46  44.906    .  1  0.163  0.435
## 7   2 1   11   7.263    .  1  1.386  0.083
## 8   2 2    0   0.331    .  1 -0.576  0.282
## 9   2 3    5   4.114    .  1  0.437  0.331
## 10  2 4    0   1.095    .  1 -1.047  0.148
## 11  2 5    2   1.910    .  1  0.065  0.474
## 12  2 6    0   3.286    .  1 -1.813  0.035
## 13  3 1  790 727.148    .  1  2.331  0.010
## 14  3 2   33  33.183    .  1 -0.032  0.487
## 15  3 3  329 411.906    -  1 -4.085  0.000
## 16  3 4   94 109.649    .  1 -1.494  0.068
## 17  3 5  195 191.165    .  1  0.277  0.391
## 18  3 6  361 328.948    .  1  1.767  0.039
## 19  4 1  160 117.022    +  1  3.973  0.000
## 20  4 2    2   5.340    .  1 -1.445  0.074
## 21  4 3   33  66.289    -  1 -4.089  0.000
## 22  4 4   13  17.646    .  1 -1.106  0.134
## 23  4 5   38  30.765    .  1  1.304  0.096
## 24  4 6   44  52.938    .  1 -1.228  0.110
## 25  5 1   22  45.195    -  1 -3.450  0.000
## 26  5 2    2   2.062    .  1 -0.043  0.483
## 27  5 3   71  25.601    +  1  8.972  0.000
## 28  5 4   11   6.815    .  1  1.603  0.054
## 29  5 5    4  11.882    .  1 -2.287  0.011
## 30  5 6    2  20.445    -  1 -4.079  0.000
## 31  6 1    9  12.106    .  1 -0.893  0.186
## 32  6 2    1   0.552    .  1  0.602  0.274
## 33  6 3   14   6.857    .  1  2.728  0.003
## 34  6 4    1   1.825    .  1 -0.611  0.271
## 35  6 5    2   3.183    .  1 -0.663  0.254
## 36  6 6    3   5.476    .  1 -1.058  0.145

In the results, we can examine the column “Type” to determine which transitions occurred more (+) or less (-) frequently than expected. We can see that the transitions between (1) discloser acknowledgements and listener elaborations, (2) discloser acknowledgements and listener hedged disclosures, (3) discloser hedged disclosures and listener acknowledgements, and (4) discloser questions and listener elaborations occurred more frequently than expected. Furthermore, transitions between (1) discloser acknowledgements and listener acknowledgements, (2) discloser elaborations and listener elaborations, (3) discloser hedged disclosures and listener elaborations, (4) discloser questions and listener acknowledgements, and (5) discloser questions and listener reflections occurred less frequently than expected.

Add Hypothetical Experimental Condition to the Data.

One particular advantage of using configural frequency analysis is that it allows researchers to examine the association between 2+ categorical variables at a time. For instance, researchers may examine the association between gender, health status, and education (or any other combination of variables that you can think of!). Stemmler and colleagues’ work provide many examples of how to examine 2+ categorical variables using configural frequency analysis.

Here, we build on our current example examining turn-to-turn transitions by adding a hypothetical variable to the data set. Specifically, we add a variable called “condition” that indicates whether the conversation occurred in a face-to-face or computer-mediated setting and randomly assign a condition to each dyad.

# Create new variable called "condition" in the data set "data"
data$condition <- NA

# Set seed for random number generator that will be used below (to make sure we get consistency across runs)
set.seed(1234)

# Randomly assign each dyad to a condition
data <- # Select data
        data %>%
        # Select grouping variable, in this case, dyad ID (id)
        dplyr::group_by(id) %>%
        # Create function that assigns a condition to each dyad
        # Within mutate, assign the condition variable a random value between 0 and 1
        # and round that value to an integer - i.e., 0 decimal places
        dplyr::group_modify(function(.x, .y) .x %>% mutate(condition = round(runif(1, 0, 1), 0))) %>%
        # Relabel the conditions
        # If condition is equal to 0, relabel it as the face-to-face condition (FtF)
        # If condition is equal to 1, relabel it as the computer-mediated communication condition (CMC)
        dplyr::mutate(condition = ifelse(condition == 0, "FtF", ifelse(condition == 1, "CMC"))) %>%
        # Save the data as a data.frame
        as.data.frame()

# View the first 10 rows of the data
head(data, 10)
##    id turn role          turn_type   lagged_turn_type condition
## 1   3    1    1      D_Elaboration               <NA>       FtF
## 2   3    2    2  L_Acknowledgement      D_Elaboration       FtF
## 3   3    3    1 D_HedgedDisclosure  L_Acknowledgement       FtF
## 4   3    4    2  L_Acknowledgement D_HedgedDisclosure       FtF
## 5   3    5    1 D_HedgedDisclosure  L_Acknowledgement       FtF
## 6   3    6    2  L_Acknowledgement D_HedgedDisclosure       FtF
## 7   3    7    1      D_Elaboration  L_Acknowledgement       FtF
## 8   3    8    2         L_Question      D_Elaboration       FtF
## 9   3    9    1      D_Elaboration         L_Question       FtF
## 10  3   10    2  L_Acknowledgement      D_Elaboration       FtF

Let’s double check to see how are random assignment worked. Specifically, we will count how many dyads ended up in each condition.

# Create dyad level data set
dyad_data <- # Select data
             data %>%
             # Select grouping variable, in this case, dyad ID (id)
             dplyr::group_by(id) %>%
             # Reduce each dyad to one row with its assigned condition
             dplyr::summarise(assigned_condition = unique(condition)) %>%
             # Count the number of dyads for each condition
             dplyr::count(assigned_condition) %>%
             # Save the data as a data.frame
             as.data.frame()

# Print data set
dyad_data
##   assigned_condition  n
## 1                CMC 29
## 2                FtF 30

Woohoo - random assignment was successful! Twenty-nine dyads were assigned to the CMC condition, and 30 dyads were assigned to the FtF condition.

Now, we get back to preparing our data for configural frequency analysis. Like we did above, we generate a data frame containing transition frequencies by condition through cross-tabulation and save it to the data frame “data_dt3” (the 3 indicating our 3 variable analysis). Because there are 7 turn types (6 identified and 1 NA), 2 roles (listener and discloser), and 2 conditions (CMC and FtF) there are 28 turn transition/condition combinations in our dataset. Thus, the crosstab table contains 28 * 28 = 784 cells, representing all combinations.

# Reformat data frame to data table
data_dt3 <- data.table::as.data.table(data)

# Count the occurrence of lagged turn and turn pairs by condition
data_counts3 <- as.data.frame(with(data_dt3, table(turn_type, lagged_turn_type, condition)))

# Count the rows in data_counts
nrow(data_counts3)
## [1] 392

As described above, not all of the 784 cells are legitimate turn transition/condition combinations. Transitions that were at the beginning or end of the conversation and those that involved uncodable turns will need to be removed. In addition, while they exist in the table, D->D and L->L transitions do not occur in our data. We will remove them in the two code chunks below.

# Remove rows in which the lagged turn in the transition contains a _NA
data_counts3 <- data_counts3[ grep("_NA", data_counts3$lagged_turn_type, invert = TRUE) , ]

# Remove rows in which the following turn in the transition contains a _NA
data_counts3 <- data_counts3[ grep("_NA", data_counts3$turn_type, invert = TRUE) , ]

# Count the rows in data_counts
nrow(data_counts3)
## [1] 288

Since we will be examining listener –> discloser and discloser –> listener turn transitions separately, we will create two different data sets that contain the counts of these turn transitions. We will also remove the L->L and D->D transitions at this step.

# Create listener --> discloser transition data set
# Remove all transitions that begin with a discloser turn from data_counts
# by selecting all rows in lagged_turn_type with the discloser tag "D_"
list2disc3 <- data_counts3[ grep("D_", data_counts3$lagged_turn_type, invert = TRUE) , ]

# Remove all transitions that end with a listener turn to create the L->D subset
# by selecting all rows in turn_type with the listener tag "L_"
list2disc3 <- list2disc3[ grep("L_", list2disc3$turn_type, invert = TRUE) , ]
nrow(list2disc3)
## [1] 72
# View the first 10 rows of the data
head(list2disc3, 10)
##              turn_type  lagged_turn_type condition Freq
## 99   D_Acknowledgement L_Acknowledgement       CMC    8
## 100           D_Advice L_Acknowledgement       CMC    4
## 101      D_Elaboration L_Acknowledgement       CMC  382
## 102 D_HedgedDisclosure L_Acknowledgement       CMC   60
## 104         D_Question L_Acknowledgement       CMC   15
## 105       D_Reflection L_Acknowledgement       CMC    1
## 113  D_Acknowledgement          L_Advice       CMC    9
## 114           D_Advice          L_Advice       CMC    1
## 115      D_Elaboration          L_Advice       CMC   17
## 116 D_HedgedDisclosure          L_Advice       CMC    2
# Create discloser --> listener transition data set
# Remove all transitions that begin with a listener turn from data_counts
# by selecting all rows in lagged_turn_type with the listener tag "L_"
disc2list3 <- data_counts3[ grep("L_", data_counts3$lagged_turn_type, invert = TRUE) , ]

# Remove all transitions that end with a discloser turn to create the D->L subset
# by selecting all rows in turn_type with the discloser tag "D_"
disc2list3 <- disc2list3[ grep("D_", disc2list3$turn_type, invert = TRUE) , ]
nrow(disc2list3)
## [1] 72
# View the first 10 rows of the data
head(disc2list3, 10)
##             turn_type  lagged_turn_type condition Freq
## 8   L_Acknowledgement D_Acknowledgement       CMC    5
## 9            L_Advice D_Acknowledgement       CMC    7
## 10      L_Elaboration D_Acknowledgement       CMC   61
## 11 L_HedgedDisclosure D_Acknowledgement       CMC   19
## 13         L_Question D_Acknowledgement       CMC    4
## 14       L_Reflection D_Acknowledgement       CMC   15
## 22  L_Acknowledgement          D_Advice       CMC    6
## 23           L_Advice          D_Advice       CMC    0
## 24      L_Elaboration          D_Advice       CMC    3
## 25 L_HedgedDisclosure          D_Advice       CMC    0

Given that we are examining the transitions between six listener turn types and six discloser turn types by condition, we should expect each of our data sets to contain 72 rows. These rows represent all possible transitions, including a few transitions that were not observed in our dataset.

Finally, the confreq package requires the data to be organized in a specific way to conduct configural frequency analysis. Specifically, each data set should have four columns that represent (1) the type of lagged turn, (2) the current type of turn, (3) the condition, and (4) the frequency of that combination. In the first three columns, each turn type and condition needs to be represented by a number instead of a category label. So, we number the turn categories in alphabetical order (1 = acknowledgement, 2 = advice, 3 = elaboration, 4 = hedged disclosure, 5 = question, 6 = reflection) and the condition as initially created above (0 = FtF, 1 = CMC). The code chunk below recodes the turn labels into numbers.

# Recoding variables in listener --> discloser transition data set
list2disc3 <- # Select data
              list2disc3 %>%  
              # Recode lagged turn and following turn variables with numbers
              dplyr::mutate(lagged_turn_type = recode(list2disc3$lagged_turn_type, 
                                              "L_Acknowledgement" = 1,
                                              "L_Advice" = 2,
                                              "L_Elaboration" = 3,
                                              "L_HedgedDisclosure" = 4,
                                              "L_Question" = 5,
                                              "L_Reflection" = 6),
                            turn_type = recode(list2disc3$turn_type, 
                                              "D_Acknowledgement" = 1,
                                              "D_Advice" = 2,
                                              "D_Elaboration" = 3,
                                              "D_HedgedDisclosure" = 4,
                                              "D_Question" = 5,
                                              "D_Reflection" = 6),
                            condition = recode(list2disc3$condition, 
                                              "FtF" = 0,
                                              "CMC" = 1)) %>%
              # Save the data as a data.frame
              as.data.frame()

# Recoding variables in discloser --> listener transition data set
disc2list3 <- # Select data
              disc2list3 %>%  
              # Recode lagged turn and following turn variables with numbers
              dplyr::mutate(lagged_turn_type = recode(disc2list3$lagged_turn_type, 
                                              "D_Acknowledgement" = 1,
                                              "D_Advice" = 2,
                                              "D_Elaboration" = 3,
                                              "D_HedgedDisclosure" = 4,
                                              "D_Question" = 5,
                                              "D_Reflection" = 6),
                            turn_type = recode(disc2list3$turn_type, 
                                              "L_Acknowledgement" = 1,
                                              "L_Advice" = 2,
                                              "L_Elaboration" = 3,
                                              "L_HedgedDisclosure" = 4,
                                              "L_Question" = 5,
                                              "L_Reflection" = 6),
                            condition = recode(disc2list3$condition, 
                                              "FtF" = 0,
                                              "CMC" = 1)) %>%
              # Save the data as a data.frame
              as.data.frame()

Let’s reorder the values of the turn variables since they represent the turn categories in alphabetical order, and reorganize the columns so the lagged turns come first.

# Order data by lagged_turn_type and turn_type for listener --> discloser turn transitions
list2disc3 <- list2disc3[order(list2disc3$lagged_turn_type, list2disc3$turn_type), ]

# Reorder the columns for listener --> discloser turn transitions
list2disc3 <- list2disc3[, c(2, 1, 3, 4)]

# View the first 10 rows of the data
head(list2disc3, 10)
##     lagged_turn_type turn_type condition Freq
## 99                 1         1         1    8
## 295                1         1         0   20
## 100                1         2         1    4
## 296                1         2         0    4
## 101                1         3         1  382
## 297                1         3         0  385
## 102                1         4         1   60
## 298                1         4         0   96
## 104                1         5         1   15
## 300                1         5         0   13
# Order data by lagged_turn_type and turn_type for discloser --> listener turn transitions
disc2list3 <- disc2list3[order(disc2list3$lagged_turn_type, disc2list3$turn_type), ]

# Reorder the columns for discloser --> listener turn transitions
disc2list3 <- disc2list3[, c(2, 1, 3, 4)]

# View the first 10 rows of the data
head(disc2list3, 10)
##     lagged_turn_type turn_type condition Freq
## 8                  1         1         1    5
## 204                1         1         0   11
## 9                  1         2         1    7
## 205                1         2         0    1
## 10                 1         3         1   61
## 206                1         3         0   58
## 11                 1         4         1   19
## 207                1         4         0   14
## 13                 1         5         1    4
## 209                1         5         0   20

We can also rename the columns to represent the speaker of that turn.

# Rename columns in listener --> discloser turn transition data
colnames(list2disc3) <- c("listener", "discloser", "condition", "freq")

# Rename columns in discloser --> listener turn transition data
colnames(disc2list3) <- c("discloser", "listener", "condition", "freq")

Conduct the Configural Frequency Analysis with Three Variables.

As before, let’s examine the structure of the data sets.

We need to check whether the variables are in the correct format. Specifically, we need the variables that label the turn types of the listeners and disclosers as well as the condition variable to be factor variables (instead of integer variables). A factor variable makes sure R interprets the variables as categories instead of integers.

# Examine the structure of the listener --> discloser 
# and discloser --> listener data
str(list2disc3)
## 'data.frame':    72 obs. of  4 variables:
##  $ listener : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ discloser: num  1 1 2 2 3 3 4 4 5 5 ...
##  $ condition: num  1 0 1 0 1 0 1 0 1 0 ...
##  $ freq     : int  8 20 4 4 382 385 60 96 15 13 ...
str(disc2list3)
## 'data.frame':    72 obs. of  4 variables:
##  $ discloser: num  1 1 1 1 1 1 1 1 1 1 ...
##  $ listener : num  1 1 2 2 3 3 4 4 5 5 ...
##  $ condition: num  1 0 1 0 1 0 1 0 1 0 ...
##  $ freq     : int  5 11 7 1 61 58 19 14 4 20 ...
# Need the discloser, listener, and condition variables to be factors in both datasets
list2disc3$listener <- as.factor(list2disc3$listener)
list2disc3$discloser <- as.factor(list2disc3$discloser)
list2disc3$condition <- as.factor(list2disc3$condition)

disc2list3$listener <- as.factor(disc2list3$listener)
disc2list3$discloser <- as.factor(disc2list3$discloser)
disc2list3$condition <- as.factor(disc2list3$condition)

Now that the data are in the correct format, we can run the configural frequency analyses.

Let’s first examine the listener to discloser transitions across conditions.

The configural frequency analysis function requires that the data are formatted as a response pattern frequency table.

# Change format of data for configural frequency analysis
# Insert data ("list2disc3") in the dat2fre(fre2dat()) function
cfa_list2disc3 <- dat2fre(fre2dat(list2disc3))
## Number of categories for each variable 
##  estimated from data are:  
##  listener discloser condition 
##  6 6 2 
##  --> 72 different configurations
# Examine the response pattern frequency table
cfa_list2disc3
##    listener discloser condition Freq
## 1         1         1         1   20
## 2         1         1         2    8
## 3         1         2         1    4
## 4         1         2         2    4
## 5         1         3         1  385
## 6         1         3         2  382
## 7         1         4         1   96
## 8         1         4         2   60
## 9         1         5         1   13
## 10        1         5         2   15
## 11        1         6         1    2
## 12        1         6         2    1
## 13        2         1         1    1
## 14        2         1         2    9
## 15        2         2         1    0
## 16        2         2         2    1
## 17        2         3         1   14
## 18        2         3         2   17
## 19        2         4         1    3
## 20        2         4         2    2
## 21        2         5         1    1
## 22        2         5         2    0
## 23        2         6         1    0
## 24        2         6         2    1
## 25        3         1         1   42
## 26        3         1         2   56
## 27        3         2         1    1
## 28        3         2         2    4
## 29        3         3         1  148
## 30        3         3         2  191
## 31        3         4         1   24
## 32        3         4         2   18
## 33        3         5         1   25
## 34        3         5         2   34
## 35        3         6         1   12
## 36        3         6         2    6
## 37        4         1         1   19
## 38        4         1         2   24
## 39        4         2         1    1
## 40        4         2         2    0
## 41        4         3         1   53
## 42        4         3         2   25
## 43        4         4         1    9
## 44        4         4         2    8
## 45        4         5         1    5
## 46        4         5         2    2
## 47        4         6         1    2
## 48        4         6         2    2
## 49        5         1         1   12
## 50        5         1         2    2
## 51        5         2         1    1
## 52        5         2         2    0
## 53        5         3         1  131
## 54        5         3         2  100
## 55        5         4         1   14
## 56        5         4         2    9
## 57        5         5         1    2
## 58        5         5         2    3
## 59        5         6         1    0
## 60        5         6         2    0
## 61        6         1         1   41
## 62        6         1         2   11
## 63        6         2         1    0
## 64        6         2         2    0
## 65        6         3         1  204
## 66        6         3         2  139
## 67        6         4         1   23
## 68        6         4         2   21
## 69        6         5         1    6
## 70        6         5         2    4
## 71        6         6         1    2
## 72        6         6         2    3

Next, we conduct the configural frequency analysis and save the results. We then examine a summary of the results.

# Conduct configural frequency analysis and save the results
# Insert the response pattern frequency table 
# and the name of the variables of interest (with a ~ and +)
results_list2disc3 <- CFA(cfa_list2disc3, form = "~ listener + discloser + condition") 

# Examine the saved results
summary(results_list2disc3 , showall = TRUE)
## function Call: 
##  ------------- 
##  Formula: ~ listener + discloser + condition 
##  Variables: listener discloser condition 
##  Categories: 6 6 2 
## 
##  results of global tests: 
##  -----------------------
##  pearson Chi-square test: 
##        Chi df pChi alpha
## 1 405.9657 60    0  0.05
## 
##  likelihood ratio test: 
##        Chi df pChi alpha
## 1 384.5246 60    0  0.05
## 
##  Information Criteria: 
##      loglik      AIC      BIC
## 1 -325.6937 675.3875 702.7075
## 
##  results of local tests: 
##  ----------------------- 
##  Type (+) / Antitype (-) based on: z.pChi ; 
##  with Bonferroni adjusted alpha: 0.0006944444
##     pat. obs.    exp. Type df  z.Chi z.pChi
## 1  1 1 1   20  51.982    -  1 -4.436  0.000
## 2  1 1 2    8  45.899    -  1 -5.594  0.000
## 3  1 2 1    4   3.395    .  1  0.328  0.371
## 4  1 2 2    4   2.997    .  1  0.579  0.281
## 5  1 3 1  385 379.576    .  1  0.278  0.390
## 6  1 3 2  382 335.158    .  1  2.559  0.005
## 7  1 4 1   96  60.893    +  1  4.499  0.000
## 8  1 4 2   60  53.768    .  1  0.850  0.198
## 9  1 5 1   13  23.339    .  1 -2.140  0.016
## 10 1 5 2   15  20.608    .  1 -1.235  0.108
## 11 1 6 1    2   6.577    .  1 -1.785  0.037
## 12 1 6 2    1   5.808    .  1 -1.995  0.023
## 13 2 1 1    1   2.573    .  1 -0.981  0.163
## 14 2 1 2    9   2.272    +  1  4.464  0.000
## 15 2 2 1    0   0.168    .  1 -0.410  0.341
## 16 2 2 2    1   0.148    .  1  2.211  0.014
## 17 2 3 1   14  18.787    .  1 -1.104  0.135
## 18 2 3 2   17  16.589    .  1  0.101  0.460
## 19 2 4 1    3   3.014    .  1 -0.008  0.497
## 20 2 4 2    2   2.661    .  1 -0.405  0.343
## 21 2 5 1    1   1.155    .  1 -0.144  0.443
## 22 2 5 2    0   1.020    .  1 -1.010  0.156
## 23 2 6 1    0   0.326    .  1 -0.571  0.284
## 24 2 6 2    1   0.287    .  1  1.329  0.092
## 25 3 1 1   42  29.457    .  1  2.311  0.010
## 26 3 1 2   56  26.010    +  1  5.881  0.000
## 27 3 2 1    1   1.924    .  1 -0.666  0.253
## 28 3 2 2    4   1.699    .  1  1.766  0.039
## 29 3 3 1  148 215.093    -  1 -4.575  0.000
## 30 3 3 2  191 189.923    .  1  0.078  0.469
## 31 3 4 1   24  34.506    .  1 -1.789  0.037
## 32 3 4 2   18  30.468    .  1 -2.259  0.012
## 33 3 5 1   25  13.225    +  1  3.238  0.001
## 34 3 5 2   34  11.678    +  1  6.532  0.000
## 35 3 6 1   12   3.727    +  1  4.285  0.000
## 36 3 6 2    6   3.291    .  1  1.493  0.068
## 37 4 1 1   19   7.876    +  1  3.964  0.000
## 38 4 1 2   24   6.954    +  1  6.464  0.000
## 39 4 2 1    1   0.514    .  1  0.677  0.249
## 40 4 2 2    0   0.454    .  1 -0.674  0.250
## 41 4 3 1   53  57.512    .  1 -0.595  0.276
## 42 4 3 2   25  50.781    -  1 -3.618  0.000
## 43 4 4 1    9   9.226    .  1 -0.074  0.470
## 44 4 4 2    8   8.147    .  1 -0.051  0.480
## 45 4 5 1    5   3.536    .  1  0.778  0.218
## 46 4 5 2    2   3.122    .  1 -0.635  0.263
## 47 4 6 1    2   0.997    .  1  1.005  0.157
## 48 4 6 2    2   0.880    .  1  1.194  0.116
## 49 5 1 1   12  14.387    .  1 -0.629  0.265
## 50 5 1 2    2  12.703    .  1 -3.003  0.001
## 51 5 2 1    1   0.940    .  1  0.062  0.475
## 52 5 2 2    0   0.830    .  1 -0.911  0.181
## 53 5 3 1  131 105.054    .  1  2.531  0.006
## 54 5 3 2  100  92.761    .  1  0.752  0.226
## 55 5 4 1   14  16.853    .  1 -0.695  0.244
## 56 5 4 2    9  14.881    .  1 -1.525  0.064
## 57 5 5 1    2   6.459    .  1 -1.755  0.040
## 58 5 5 2    3   5.704    .  1 -1.132  0.129
## 59 5 6 1    0   1.820    .  1 -1.349  0.089
## 60 5 6 2    0   1.607    .  1 -1.268  0.102
## 61 6 1 1   41  23.838    +  1  3.515  0.000
## 62 6 1 2   11  21.049    .  1 -2.190  0.014
## 63 6 2 1    0   1.557    .  1 -1.248  0.106
## 64 6 2 2    0   1.375    .  1 -1.172  0.121
## 65 6 3 1  204 174.068    .  1  2.269  0.012
## 66 6 3 2  139 153.699    .  1 -1.186  0.118
## 67 6 4 1   23  27.925    .  1 -0.932  0.176
## 68 6 4 2   21  24.657    .  1 -0.736  0.231
## 69 6 5 1    6  10.703    .  1 -1.438  0.075
## 70 6 5 2    4   9.450    .  1 -1.773  0.038
## 71 6 6 1    2   3.016    .  1 -0.585  0.279
## 72 6 6 2    3   2.663    .  1  0.206  0.418

In the results, we can examine the column “Type” to determine which transitions occurred more (+) or less (-) frequently than expected.

For the face-to-face condition, we see that the transitions between (1) listener acknowledgements and discloser hedged disclosures, (2) listener elaborations and discloser questions, (3) listener elaborations and discloser reflections, (4) listener hedged disclosures and discloser acknowledgements, and (5) listener reflections and discloser acknowledgements occurred more frequently than expected. Furthermore, transitions between (1) listener acknowledgements and discloser acknowledgements and (2) listener elaborations and discloser elaborations occurred less frequently than expected.

For the computer-mediated communication condition, we see that the transitions between (1) listener advice and discloser acknowledgements, (2) listener elaborations and discloser acknowledgements, (3) listener elaborations and discloser questions, and (4) listener hedged disclosures and discloser acknowledgements occurred more frequently than expected. Furthermore, transitions between (1) listener acknowledgements and discloser acknowledgements and (2) listener hedged disclosures and discloser elaborations occurred less frequently than expected.

We next examine the discloser to listener transitions across conditions.

The configural frequency analysis function requires that the data are formatted as a response pattern frequency table.

# Change format of data for configural frequency analysis
# Insert data (disc2list3) in the dat2fre(fre2dat()) function
cfa_disc2list3 <- dat2fre(fre2dat(disc2list3))
## Number of categories for each variable 
##  estimated from data are:  
##  discloser listener condition 
##  6 6 2 
##  --> 72 different configurations
# Examine the response pattern frequency table
cfa_disc2list3
##    discloser listener condition Freq
## 1          1        1         1   11
## 2          1        1         2    5
## 3          1        2         1    1
## 4          1        2         2    7
## 5          1        3         1   58
## 6          1        3         2   61
## 7          1        4         1   14
## 8          1        4         2   19
## 9          1        5         1   20
## 10         1        5         2    4
## 11         1        6         1   31
## 12         1        6         2   15
## 13         2        1         1    5
## 14         2        1         2    6
## 15         2        2         1    0
## 16         2        2         2    0
## 17         2        3         1    2
## 18         2        3         2    3
## 19         2        4         1    0
## 20         2        4         2    0
## 21         2        5         1    1
## 22         2        5         2    1
## 23         2        6         1    0
## 24         2        6         2    0
## 25         3        1         1  400
## 26         3        1         2  390
## 27         3        2         1   14
## 28         3        2         2   19
## 29         3        3         1  145
## 30         3        3         2  184
## 31         3        4         1   63
## 32         3        4         2   31
## 33         3        5         1  107
## 34         3        5         2   88
## 35         3        6         1  214
## 36         3        6         2  147
## 37         4        1         1   97
## 38         4        1         2   63
## 39         4        2         1    1
## 40         4        2         2    1
## 41         4        3         1   15
## 42         4        3         2   18
## 43         4        4         1    8
## 44         4        4         2    5
## 45         4        5         1   21
## 46         4        5         2   17
## 47         4        6         1   27
## 48         4        6         2   17
## 49         5        1         1   15
## 50         5        1         2    7
## 51         5        2         1    1
## 52         5        2         2    1
## 53         5        3         1   25
## 54         5        3         2   46
## 55         5        4         1    8
## 56         5        4         2    3
## 57         5        5         1    3
## 58         5        5         2    1
## 59         5        6         1    2
## 60         5        6         2    0
## 61         6        1         1    5
## 62         6        1         2    4
## 63         6        2         1    0
## 64         6        2         2    1
## 65         6        3         1    8
## 66         6        3         2    6
## 67         6        4         1    1
## 68         6        4         2    0
## 69         6        5         1    1
## 70         6        5         2    1
## 71         6        6         1    3
## 72         6        6         2    0

Next, we conduct the configural frequency analysis and save the results. We then examine a summary of the results.

# Conduct configural frequency analysis and save the results
# Insert the response pattern frequency table 
# and the name of the variables of interest (with a ~ and +)
results_disc2list3 <- CFA(cfa_disc2list3, form = "~ listener + discloser + condition") 

# Examine the saved results
summary(results_disc2list3 , showall = TRUE)
## function Call: 
##  ------------- 
##  Formula: ~ listener + discloser + condition 
##  Variables: discloser listener condition 
##  Categories: 6 6 2 
## 
##  results of global tests: 
##  -----------------------
##  pearson Chi-square test: 
##        Chi df pChi alpha
## 1 458.1574 60    0  0.05
## 
##  likelihood ratio test: 
##       Chi df pChi alpha
## 1 456.942 60    0  0.05
## 
##  Information Criteria: 
##      loglik      AIC      BIC
## 1 -359.3389 742.6778 769.9978
## 
##  results of local tests: 
##  ----------------------- 
##  Type (+) / Antitype (-) based on: z.pChi ; 
##  with Bonferroni adjusted alpha: 0.0006944444
##     pat. obs.    exp. Type df  z.Chi z.pChi
## 1  1 1 1   11  52.733    -  1 -5.747  0.000
## 2  1 1 2    5  46.534    -  1 -6.089  0.000
## 3  1 2 1    1   2.406    .  1 -0.907  0.182
## 4  1 2 2    7   2.124    +  1  3.346  0.000
## 5  1 3 1   58  29.872    +  1  5.147  0.000
## 6  1 3 2   61  26.360    +  1  6.747  0.000
## 7  1 4 1   14   7.952    .  1  2.145  0.016
## 8  1 4 2   19   7.017    +  1  4.524  0.000
## 9  1 5 1   20  13.863    .  1  1.648  0.050
## 10 1 5 2    4  12.234    .  1 -2.354  0.009
## 11 1 6 1   31  23.855    .  1  1.463  0.072
## 12 1 6 2   15  21.051    .  1 -1.319  0.094
## 13 2 1 1    5   3.859    .  1  0.581  0.281
## 14 2 1 2    6   3.405    .  1  1.406  0.080
## 15 2 2 1    0   0.176    .  1 -0.420  0.337
## 16 2 2 2    0   0.155    .  1 -0.394  0.347
## 17 2 3 1    2   2.186    .  1 -0.126  0.450
## 18 2 3 2    3   1.929    .  1  0.771  0.220
## 19 2 4 1    0   0.582    .  1 -0.763  0.223
## 20 2 4 2    0   0.513    .  1 -0.717  0.237
## 21 2 5 1    1   1.014    .  1 -0.014  0.494
## 22 2 5 2    1   0.895    .  1  0.111  0.456
## 23 2 6 1    0   1.746    .  1 -1.321  0.093
## 24 2 6 2    0   1.540    .  1 -1.241  0.107
## 25 3 1 1  400 386.279    .  1  0.698  0.243
## 26 3 1 2  390 340.869    .  1  2.661  0.004
## 27 3 2 1   14  17.628    .  1 -0.864  0.194
## 28 3 2 2   19  15.556    .  1  0.873  0.191
## 29 3 3 1  145 218.815    -  1 -4.990  0.000
## 30 3 3 2  184 193.091    .  1 -0.654  0.256
## 31 3 4 1   63  58.248    .  1  0.623  0.267
## 32 3 4 2   31  51.401    .  1 -2.846  0.002
## 33 3 5 1  107 101.552    .  1  0.541  0.294
## 34 3 5 2   88  89.613    .  1 -0.170  0.432
## 35 3 6 1  214 174.745    .  1  2.970  0.001
## 36 3 6 2  147 154.203    .  1 -0.580  0.281
## 37 4 1 1   97  62.165    +  1  4.418  0.000
## 38 4 1 2   63  54.857    .  1  1.099  0.136
## 39 4 2 1    1   2.837    .  1 -1.091  0.138
## 40 4 2 2    1   2.503    .  1 -0.950  0.171
## 41 4 3 1   15  35.214    -  1 -3.406  0.000
## 42 4 3 2   18  31.075    .  1 -2.345  0.010
## 43 4 4 1    8   9.374    .  1 -0.449  0.327
## 44 4 4 2    5   8.272    .  1 -1.138  0.128
## 45 4 5 1   21  16.343    .  1  1.152  0.125
## 46 4 5 2   17  14.422    .  1  0.679  0.249
## 47 4 6 1   27  28.122    .  1 -0.212  0.416
## 48 4 6 2   17  24.816    .  1 -1.569  0.058
## 49 5 1 1   15  24.008    .  1 -1.839  0.033
## 50 5 1 2    7  21.186    .  1 -3.082  0.001
## 51 5 2 1    1   1.096    .  1 -0.091  0.464
## 52 5 2 2    1   0.967    .  1  0.034  0.487
## 53 5 3 1   25  13.600    .  1  3.091  0.001
## 54 5 3 2   46  12.001    +  1  9.814  0.000
## 55 5 4 1    8   3.620    .  1  2.302  0.011
## 56 5 4 2    3   3.195    .  1 -0.109  0.457
## 57 5 5 1    3   6.312    .  1 -1.318  0.094
## 58 5 5 2    1   5.570    .  1 -1.936  0.026
## 59 5 6 1    2  10.861    .  1 -2.689  0.004
## 60 5 6 2    0   9.584    .  1 -3.096  0.001
## 61 6 1 1    5   6.431    .  1 -0.564  0.286
## 62 6 1 2    4   5.675    .  1 -0.703  0.241
## 63 6 2 1    0   0.293    .  1 -0.542  0.294
## 64 6 2 2    1   0.259    .  1  1.456  0.073
## 65 6 3 1    8   3.643    .  1  2.283  0.011
## 66 6 3 2    6   3.215    .  1  1.554  0.060
## 67 6 4 1    1   0.970    .  1  0.031  0.488
## 68 6 4 2    0   0.856    .  1 -0.925  0.177
## 69 6 5 1    1   1.691    .  1 -0.531  0.298
## 70 6 5 2    1   1.492    .  1 -0.403  0.344
## 71 6 6 1    3   2.909    .  1  0.053  0.479
## 72 6 6 2    0   2.567    .  1 -1.602  0.055

In the results, we can examine the column “Type” to determine which transitions occurred more (+) or less (-) frequently than expected.

For the face-to-face condition, we see that the transitions between (1) discloser acknowledgements and listener elaborations and (2) discloser hedged disclosures and listener acknowledgements occurred more frequently than expected. Furthermore, transitions between (1) discloser acknowledgements and listener acknowledgements, (2) discloser elaborations and listener elaborations, and (3) discloser hedged disclosures and listener elaborations occurred less frequently than expected.

For the computer-mediated communication condition, we see that the transitions between (1) discloser acknowledgements and listener advice, (2) discloser acknowledgements and listener elaborations, (3) discloser acknowledgements and listener hedged disclosures, and (4) discloser questions and listener elaborations occurred more frequently than expected. Furthermore, transitions between discloser acknowledgements and listener acknowledgements occurred less frequently than expected.


Additional Information

We created this tutorial with a system environment and versions of R and packages that might be different from yours. If R reports errors when you attempt to run this tutorial, running the code chunk below and comparing your output and the tutorial posted on the LHAMA website may be helpful.

session_info(pkgs = c("attached"))
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value
##  version  R version 4.2.0 (2022-04-22)
##  os       macOS Big Sur/Monterey 10.16
##  system   x86_64, darwin17.0
##  ui       X11
##  language (EN)
##  collate  en_US.UTF-8
##  ctype    en_US.UTF-8
##  tz       America/New_York
##  date     2023-06-16
##  pandoc   2.18 @ /Applications/RStudio.app/Contents/MacOS/quarto/bin/tools/ (via rmarkdown)
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package    * version date (UTC) lib source
##  confreq    * 1.5.6-7 2022-04-12 [1] CRAN (R 4.2.0)
##  data.table * 1.14.2  2021-09-27 [1] CRAN (R 4.2.0)
##  devtools   * 2.4.3   2021-11-30 [1] CRAN (R 4.2.0)
##  dplyr      * 1.0.9   2022-04-28 [1] CRAN (R 4.2.0)
##  forcats    * 0.5.1   2021-01-27 [1] CRAN (R 4.2.0)
##  ggplot2    * 3.3.6   2022-05-03 [1] CRAN (R 4.2.0)
##  gmp        * 0.6-5   2022-03-17 [1] CRAN (R 4.2.0)
##  purrr      * 0.3.4   2020-04-17 [1] CRAN (R 4.2.0)
##  readr      * 2.1.2   2022-01-30 [1] CRAN (R 4.2.0)
##  stringr    * 1.4.0   2019-02-10 [1] CRAN (R 4.2.0)
##  tibble     * 3.1.7   2022-05-03 [1] CRAN (R 4.2.0)
##  tidyr      * 1.2.0   2022-02-01 [1] CRAN (R 4.2.0)
##  tidyverse  * 1.3.1   2021-04-15 [1] CRAN (R 4.2.0)
##  usethis    * 2.1.5   2021-12-09 [1] CRAN (R 4.2.0)
##  vcd        * 1.4-10  2022-06-09 [1] CRAN (R 4.2.0)
## 
##  [1] /Library/Frameworks/R.framework/Versions/4.2/Resources/library
## 
## ──────────────────────────────────────────────────────────────────────────────