2

Background Information

I have been running mediation analysis using the mediate function available in the R Mediation Package by Tingley et. al. I have run this package on a series of iterations of regressions, and it has left me with approximately 50 mediation objects.

Unfortunately, the mediation package does not seem to have an easy way to export the summaries of these objects, and it is not supported by stargazer. Therefore, I figured that I would try to extract the desired information from these objects myself and package them into a data frame.

What I want to do

I want to extract specific components from each mediation object and insert them as a row into a new data frame. This is what I want the data to look like:

MEDIATION     ACME    ACME 95H    ACME95L   ACMEP   ...   N.OBS
Mediation 1   0.809   1.201       0.756     0.02    ...   3154
Mediation 2   0.765   0.829       0.711     0.05    ...   3154
Mediation 3   0.050   0.159      -0.056     0.76    ...   3154

I have searched through the mediation objects and found the corresponding components for each of the items that I would like to extract. My thinking was that I would use a loop to generate a dataset that would assign each mediation object a single row, and would array the specified data in wide form.

Reproducible Example

Below is a reproducible version of running the basic mediation. For the sake of example, I use the swiss data, which are pre-packaged with R.

# Use `swiss` data
summary(swiss)

# use `mediation` package
library(mediation)

# Run the regression for the IV effect on mediator
med.m <- lm(Catholic ~ Education, data = swiss)

# Run the regression for the full model, including mediator
med.y <- lm(Infant.Mortality ~ Education + Catholic, data = swiss)

# Run the mediation analysis, with the IV set as "Education and the mediator set as "Catholic"
Mediation.1<- mediate(med.m, med.y, sims = 1000, treat = "Education", mediator = "Catholic")

# Inspect the Mediation
summary(medsummary)   

Here is what I tried to do when extracting the components of the mediation object:

# Create a list of the mediations
mediations <- c("Mediation.1", "Mediation.2", "Mediation.3", ..., "Mediation 50")

# Create an empty data frame
med.df <- data.frame(matrix(NA, nrow = 51, ncol = 20))

# Loop through data and extract components
for (c in seq(1:51)){
    for (i in mediations){
        med.df[c,] <- c("i", i[[1]]1, i[[3]][1], i[[3]][2], i[[5]][1], [[92]])
    }
}

Unfortunately, this just results in the data frame looking like this:

1  i Mediation.1     i Mediation.1    i Mediation.1    i Mediation.1    i Mediation.1
2  i Mediation.1     i Mediation.1    i Mediation.1    i Mediation.1    i Mediation.1
3  i Mediation.1     i Mediation.1    i Mediation.1    i Mediation.1    i Mediation.1

Would someone be willing to help me understand what I'm doing wrong, and how to fix this?

Thank you!

r2evans
  • 141,215
  • 6
  • 77
  • 149
Yasha
  • 330
  • 2
  • 16
  • It seems that there are several issues with your code. Can you provide a reproducible example. – Alex Aug 27 '16 at 22:32
  • Hi @Alex, I am not sure that I quite understand. I did post my code. Aside from posting the contents of one of the mediation objects, I don't know what else to post. – Yasha Aug 27 '16 at 22:37
  • Examples: your first line (`mediations <- ...`) appears to be a placeholder, not real code (it doesn't work); your indexing within the inner `for` loop is inconsistent and equally incorrect. It would help to provide *input data* that can be used with *sample code* to run functions from the `mediation` package, get the output, and try to replicate what you are attempting to create. Please edit your question using these references: [help/mcve](http://stackoverflow.com/help/mcve) and [reproducible examples](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – r2evans Aug 27 '16 at 22:47
  • Can you make up some sample data which are as minimal as possible but also provides everything needed for others to reproduce the problem. – Alex Aug 27 '16 at 22:48
  • I have now included a reproducible example! – Yasha Aug 27 '16 at 23:10
  • If you look on pg.15 of your link (the module's documentation), you will see all items of the `mediate()` function. Some are vectors themselves of multiple values which cannot fill a cell of a matrix/dataframe. Scalar values like `nobs` would be best. So, you need to decide what data pts. to keep for df. – Parfait Aug 28 '16 at 01:14
  • There are some problems in your example. I notice `i[[1]]1` in the for loop - should the 1 be on the end? Also in the loop is `[[92]]`. Should there be an `i` in front of this? Aside, using `c` as a variable in your for loop is not a great idea, because `c()` is a function. – Simon Jackson Aug 28 '16 at 05:51

1 Answers1

0

You have the right idea! If you have a bunch of bunch of objects with similar names floating in your environment, specifying them with strings rather than hardcoding something in is a good idea. I don't know the specifics of the mediation package, so I'm going to assume that:

  • You have fifty regression objects in your environment named Mediation.n, where n is a number in the range 1:50, and
  • You want to save the properties property1, property2 and property3 of these objects to the data frame (I don't know specifically what you want to save, but I'm going to assume that you know how to access those properties through $property1 or [['property1']] syntax).

Here's my version:

# here's a shorter way to get your variable names together
med.names = paste('Mediations', 1:5, sep = '.')

# results df (no need to preallocate rows!)
# sub other data types (eg. numeric()) for character() to taste
med.df = data.frame(
    name = character(0)
    property1 = character(0),
    property2 = character(0),
    property3 = character(0))

for (med.name.current in med.names)
{
    # med.s is a string: the name of the object
    # we need the object itself
    med.i = get(med.name.current)

    # we're going to glue the current med.df column-wise to
    # another, new df with just one row.
    # it'll have the same col names as the current one!
    med.df = rbind(med.df, data.frame(
        name = med.name.current,
        property1 = med.i$property1,
        property2 = med.i$property2,
        property3 = med.i$property3))
}

# now do whatever you like with med.df!

Is this what you're looking for? There are two important bits to note here:

  1. If you're going to use strings to specify objects in the environment, you need to give the string to the get() function, which will return the object in question. You can't just plonk the strings together in your code.
  2. We tend to think about data frames as being a list of rows, but they're actually a list of columns. So you can't add a row by specifying it with c(). Instead, you need to create a new data frame, then join it to the old one column-wise (horizontally, if you will) with rbind(). (Just FYI, you can also glue a vector or data frame to another vector or data frame row-wise, or vertically, using cbind()!)

Finally, as @SimonJackson notes, using the variable name c is a great way to prematurely age, as it's already used by the function c(), which creates vectors. If you assign to it, you might not be able to use c() anymore.

I hope that helps!

jimjamslam
  • 1,988
  • 1
  • 18
  • 32