1#' Write Amelia imputations to file
2#'
3#' Writes the imptuted datasets to file from a run of \code{amelia}
4#'
5#' @param obj an object of class "amelia"; typically output from the
6#'     function \code{amelia}
7#' @param separate logical variable. If \code{TRUE} (default), the
8#'     imputed datasets will be written to separate files, whose names come
9#'     from the \code{file.stem} and \code{extension} arguments. If \code{FALSE},
10#'     the imputations are stacked and written as a single file.
11#' @param file.stem the leading part of the filename to save to
12#'     output The imputation number and \code{extension} will be added to
13#'     complete the filename. This can include a directory path.
14#' @param extension the extension of the filename. This is simply what
15#'     follows \code{file.stem} and the imputation number.
16#' @param format one of the following output formats: \code{csv},
17#'     \code{dta} or \code{table}. See details.
18#' @param impvar the name of imputation number variable written to the
19#'     stacked dataset when \code{separate} is \code{FALSE}.
20#' @param orig.data logical variable indicating whether the original,
21#'     unimputed dataset should be included in the stacked dataset when
22#'     \code{separate} is \code{FALSE}.
23#' @param \dots further arguments for the \code{write} functions.
24#'
25#' @details
26#'   \code{write.amelia} writes the imputed datasets to a file or a set of files
27#' using one of the following functions: \code{write.csv},
28#' \code{write.dta}, or \code{write.table}. You can pass arguments to
29#' these functions from \code{write.amelia}.
30#'
31#' When \code{separate} is \code{TRUE}, each imputed dataset is written
32#' to its own file. If you were to set \code{file.stem} to
33#' \code{"outdata"} and the \code{extension} to \code{".csv"} , then the
34#' resulting filename of the written files will be
35#' \preformatted{
36#'   outdata1.csv
37#'   outdata2.csv
38#'   outdata3.csv
39#'   ...
40#' }
41#' and so on.
42#'
43#' When \code{separate} is \code{FALSE}, the function adds a variable
44#' called \code{impvar} to each dataset which indicates the imputed
45#' dataset to which the row belongs. Then, each of the datasets are
46#' stacked together to create one dataset. If \code{orig.data} is \code{TRUE},
47#' then the original, unimputed dataset is included at the top of the
48#' stack, with its imputation number set to 0.
49#'
50#' @seealso \code{\link{write.csv}}, \code{\link{write.table}}, \code{\link{write.dta}}
51
52write.amelia <- function(obj, separate = TRUE, file.stem,
53                         extension = NULL, format = "csv",
54                         impvar = "imp", orig.data = TRUE, ...) {
55
56  if(!(format %in% c("csv","table","dta"))) {
57    stop("The writing format is not supported")
58  }
59
60  ## smart defaults for the extensions
61  if (missing(extension)) {
62    if (format == "dta") extension <- ".dta"
63    if (format == "csv") extension <- ".csv"
64  }
65
66  m <- length(obj$imputations)
67  Call <- match.call(expand.dots = TRUE)
68  Call[[1]] <- as.name(paste("write",format, sep="."))
69
70  ## these arugments should not be passed to write.format
71  Call$obj <- NULL
72  Call$file.stem <- NULL
73  Call$extension <- NULL
74  Call$format <- NULL
75  Call$separate <- NULL
76  Call$orig.data <- NULL
77  Call$impvar <- NULL
78
79  if (separate) {
80    for (i in 1:m) {
81      if (format == "dta")
82        Call$dataframe <- obj$imputations[[i]]
83      else
84        Call$x <- obj$imputations[[i]]
85
86      Call$file <- paste(file.stem, i, extension,sep="")
87      eval.parent(Call)
88    }
89  } else {
90    if (orig.data) {
91      odata <- obj$imputations[[1]]
92      is.na(odata) <- obj$missMatrix
93      odata[, impvar] <- 0
94    }
95    obj$imputations[[1]][, impvar] <- 1
96
97    if (orig.data) {
98      obj$imputations[[1]] <- rbind(odata, obj$imputations[[1]])
99    }
100    if (format == "dta") {
101      Call$dataframe <- obj$imputations[[1]]
102    } else {
103      Call$x <- obj$imputations[[1]]
104    }
105    for (i in 2:m) {
106      obj$imputations[[i]][, impvar] <- i
107      if (format == "dta") {
108        Call$dataframe <- rbind(Call$dataframe, obj$imputations[[i]])
109      } else {
110        Call$x <- rbind(Call$x, obj$imputations[[i]])
111      }
112    }
113    Call$file <- paste(file.stem, extension, sep = "")
114    eval.parent(Call)
115  }
116  invisible()
117}
118