knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)

inteRact

The goal of inteRact is to make affect control theory (ACT) equations accessible to a broader audience of social scientists.

ACT is a theory of social behavior that rests upon a control process in which people act in ways that maintain cultural meaning. ACT theoretical concepts have been fruitful when applied to research within cultural sociology (Hunzaker 2014, 2018), stratification and occupational prestige (Freeland and Hoey 2018), social movements (shuster and Campos-Castillo. 2017), and gender and victimization (Boyle and McKinzie 2015; Boyle and Walker 2016). Information about ACT as a theory can be accessed here: https://research.franklin.uga.edu/act/

The goal of this package is to make elements of typical ACT analyses easier to implement into R: calculating the deflection of an event, the optimal behavior of an actor after an event, the relabeling of the actor or object after an event, and calculating emotions within events. You can look within the functions to see how the equations were programmed, but to truly get a handle on the equations and how they work, I refer you to Expressive Order (Heise 2010).

Installation

You can install the development version from GitHub with:

# install.packages("devtools")
devtools::install_github("ekmaloney/inteRact")

Example Analysis

The following analysis is an example of how to use this package to implement ACT equations in your work. Because interact.jar is an excellent Java program intended for the use of examining single events in great detail, inteRact privileges workflows that intend to apply Affect Control Theory equations to many events at once. Functions can still be applied to one event, but the steps required to apply the functions may seem onerous for only one single event.

First, for any analysis you do, you need to ensure that the identities, behaviors, and modifiers that you study are measured in an ACT dictionary. inteRact requires the use of an accompanying data package, actdata, maintained by Aidan Combs and accessible here (https://github.com/ahcombs/actdata). In the following analysis, I will be using the most recent US dictionary, the US Full Surveyor Dictionary collected in 2015.

The first step in an analysis is to create a data frame of events - these events should follow the actor-behavior-object format of a typical ACT interaction. This data frame can either be wide (a column each for actor, behavior, and object), or long (multiple rows per event).

library(inteRact)
library(actdata)
library(tidyverse)

#get US 2015 dictionary using the epa subset from the actdata package
us_2015 <- epa_subset(dataset = "usfullsurveyor2015")

#make a dataframe of events 
set.seed(369)
events_wide <- tibble(actor = sample(us_2015$term[us_2015$component == "identity"], 10),
                 behavior = sample(us_2015$term[us_2015$component == "behavior"], 10),
                 object = sample(us_2015$term[us_2015$component == "identity"], 10))

set.seed(369)
events_long <- tibble(id = rep(1:10, 3),
                      term = c(sample(us_2015$term[us_2015$component == "identity"], 10),
                               sample(us_2015$term[us_2015$component == "behavior"], 10),
                               sample(us_2015$term[us_2015$component == "identity"], 10)),
                      element = rep(c("actor", "behavior", "object"), each = 10)) %>% 
                arrange(id)

head(events_wide)
head(events_long)

The next step is to augment your events with the corresponding EPA measures from the ACT dictionary. To do this, you should use the reshape_events_df on your events dataframe. You must indicate the dictionary you are using by its actdata key (in this case "usfullsurveyor2015") and the gender of those dictionary estimates (here I am using the average of the male and female estimates). This function has an indicator whether your events dataframe is wide or long - if it is long, you must use the id_column argument to indicate the variable that you are using to group the events by.

analysis_df <- reshape_events_df(df = events_wide,
                                 df_format = "wide",
                                 dictionary_key = "usfullsurveyor2015",
                                 dictionary_gender = "average")

head(analysis_df)

analysis_df <- reshape_events_df(df = events_long,
                                 df_format = "long",
                                 id_column = "id",
                                 dictionary_key = "usfullsurveyor2015",
                                 dictionary_gender = "average")

head(analysis_df)

After reshaping your events, you now have a dataframe with the fundamental sentiments of each element of your Actor-Behavior-Object events. In ACT, fundamental sentiments are the stable cultural meaning of a social identity, behavior, or emotion. These sentiments fall along 3 dimensions: Evaluation, how good or bad the concept is, Potency, how powerful or weak, and Activity, how fast/young or slow/old. Values of these dimensions range from -4.3 (extremely bad, weak, slow) to 4.3 (extremely good, powerful, active).

Once you have the overall analysis dataframe, you should group_by the event_id and nest the rest of the data, this will allow you to apply the main ACT functions to each event in the dataframe. Next, you should add a column indicating the equation you will be using to analyze the events. This should take the form "{equation_key}_{gender}" from the actdata package. In the following code, you will see that I am using the us2010 equation averaged across genders to match the dictionary.

nested_analysis_df <- analysis_df %>% 
                      group_by(event_id, event) %>% 
                      nest() %>% 
                      mutate(eq_info = "us2010_average")

Now, you can apply various functions to each event by using the map2() function from the purrr package. For example, to get the deflection of each event, you use the map2 function to iteratively apply the get_deflection function to each dataframe of events and equation information inside the nested dataframe.

results_df <- nested_analysis_df %>% 
              mutate(deflection = map2_dbl(data, eq_info, get_deflection))

results_df %>% select(event, deflection)

Deflection

When applying Affect Control Theory in research contexts, one of the most typical questions is - what is the deflection of this event? The deflection is an indicator of how culturally unlikely an event is to occur - a higher deflection indicates a more unexpected event. ACT calculates how much each element (Actor, Behavior, Object) moves along each dimension (Evaluation, Potency, Activity) after an event - these new locations in EPA space are termed the transient impressions. The deflection is the sum of squared differences between the fundamental sentiments and transient impressions for each element of the event.

You can replicate the results from the get_deflection function by calculating the transient impression of each event, calculating the squared differences between fundamental sentiments and transient impressions, squaring them, and then summing those squared differences.

nested_analysis_df %>% 
    mutate(trans_imp = map2(data, eq_info, transient_impression)) %>% 
    unnest(trans_imp) %>% 
    mutate(difference = estimate - trans_imp,
           sqd_difference = difference^2) %>% 
    group_by(event_id, event) %>% 
    summarise(deflection = sum(sqd_difference))

Element Deflection

You may even be particularly interested in which element-dimensions move the most in EPA space from your events.

nested_analysis_df %>% 
    mutate(elem_def = map2(data, eq_info, element_deflection)) %>% 
    unnest(elem_def) %>% ggplot(mapping = aes(x = sqd_diff)) + 
      geom_histogram(binwidth = 0.5) + facet_grid(dimension ~ element) + 
      theme_minimal() + labs(x = "Squared Difference between Fundamental and Transient")

Optimal Behavior

ACT can also predict the optimal behavior for the actor to enact in the following interaction that would bring the transient sentiments back as close as possible to the fundamental sentiments. The function optimal_behavior finds the E, P, and A value for the optimal behavior

nested_analysis_df %>% 
  mutate(opt_beh = map2(data, eq_info, optimal_behavior)) %>% 
  unnest(opt_beh)

Actor and Object Reidentification

Following an ABO event, Actors and Objects can be reidentified by the other or an onlooker, to an identity that "fits" with their behavior better. The functions reidentify_actor and reidentify_object calculate this for you:

nested_analysis_df %>% 
  mutate(new_actor_id = map2(data, eq_info, reidentify_actor),
         new_object_id = map2(data, eq_info, reidentify_object)) %>% 
  unnest(new_actor_id)

Closest Term

To find the closest measured identity, modifier, or behavior to an EPA profile, you can use the function closest_term which has 5 arguments: the E, P, and A measurements, the type of term (identity, modifier, or behavior, and the maximum distance away in EPA units the term can be).

nested_analysis_df %>% 
  mutate(new_actor_id = map2(data, eq_info, reidentify_actor),
         new_object_id = map2(data, eq_info, reidentify_object)) %>% 
  unnest(new_actor_id) %>% 
  rowwise() %>% 
  mutate(term = closest_term(E, P, A, dictionary_key = "usfullsurveyor2015", gender = "average",
               term_typ = "identity", num_terms = 1)) %>% 
  unnest(cols = c(term))


ekmaloney/inteRact documentation built on Feb. 20, 2023, 1:29 p.m.