File: sample.R

package info (click to toggle)
r-cran-rpf 1.0.11%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,484 kB
  • sloc: cpp: 5,364; sh: 114; ansic: 41; makefile: 2
file content (133 lines) | stat: -rw-r--r-- 4,963 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
##' Randomly sample response patterns given a list of items
##'
##' Returns a random sample of response patterns given a list of item
##' models and parameters. If \code{grp} is given then theta, items, params,
##' mean, and cov can be omitted.
##'
##' @template detail-group
##' @name rpf.sample
##' @param theta either a vector (for 1 dimension) or a matrix (for >1
##' dimension) of person abilities or the number of response patterns
##' to generate randomly
##' @param items a list of item models
##' @param params a list or matrix of item parameters. If omitted, random item
##' parameters are generated for each item model.
##' @template arg-dots
##' @param prefix Column names are taken from param or items.
##' If no column names are available, some will be generated using
##' the given prefix.
##' @param mean mean vector of latent distribution (optional)
##' @param cov covariance matrix of latent distribution (optional)
##' @param mcar proportion of generated data to set to NA (missing completely at random)
##' @template arg-grp
##' @return Returns a data frame of response patterns
##' @examples
##' # 1 dimensional items
##' i1 <- rpf.drm()
##' i1.p <- rpf.rparam(i1)
##' i2 <- rpf.nrm(outcomes=3)
##' i2.p <- rpf.rparam(i2)
##' rpf.sample(5, list(i1,i2), list(i1.p, i2.p))
##' @seealso \code{\link{sample}}
rpf.sample <- function(theta, items, params, ..., prefix="i",
                       mean=NULL, cov=NULL, mcar=0.0, grp=NULL)
{
    garbageArguments <- list(...)
    if (length(garbageArguments) > 0) {
        stop("rpf.sample does not accept values for the '...' argument")
    }

    if (!missing(grp)) {
	    if (missing(items)) items <- grp$spec
	    if (missing(params) && !is.null(grp$param)) params <- grp$param
	    if (missing(mean) && !is.null(grp$mean)) mean <- grp$mean
	    if (missing(cov) && !is.null(grp$cov)) cov <- grp$cov
	    if (missing(theta) && !is.null(grp$data)) theta <- nrow(grp$data)
    }

  numItems <- length(items)
  maxDim <- max(vapply(items, function(i) i@factors, 0))

    if (maxDim > 1) {
	    design <- matrix(rep(1:maxDim, numItems), nrow=maxDim)
	    design[sapply(items, function(i) 1:maxDim > i@factors)] <- NA
    } else {
	    design <- matrix(rep(1, numItems), nrow=1)
    }

  maxAbilities <- max(design, na.rm=TRUE)

  numPeople <- NA
  if (is.numeric(theta) && length(theta) == 1) {
    if (theta <= 1) stop("Request at least 2 samples")
    numPeople <- theta
    if (missing(mean)) mean <- rep(0, maxAbilities)
    if (length(mean) != maxAbilities) stop(paste("Mean vector must have length",maxAbilities,"not",length(mean)))
    if (missing(cov)) cov <- diag(maxAbilities)
    if (any(dim(cov) != maxAbilities)) stop(paste("Cov matrix must be square matrices of size",maxAbilities))
    theta <- array(t(mvtnorm::rmvnorm(numPeople, mean=mean, sigma=cov)),
                   dim=c(maxAbilities, numPeople))
  } else if (maxDim == 1 && is.vector(theta)) {
    numPeople <- length(theta)
    theta <- array(theta, dim=c(maxAbilities, numPeople))
  } else {
      if (dim(theta)[1] > maxAbilities) {
          stop(paste("Only", maxAbilities, "abilities but theta provides", dim(theta)[1],
                     "-- maybe transpose theta?"))
      }
    numPeople <- dim(theta)[2]
  }

  if (missing(params)) {
    params <- lapply(items, rpf.rparam)
  }

  outcomes <- vapply(items, function(i) i@outcomes, 0)

  name <- colnames(params)
  if (is.null(name)) name <- names(items)

    maxParam <- max(sapply(items, rpf.numParam))
    if (is.matrix(params) && nrow(params) > maxParam) {
	    warning(paste("Item parameter matrix has", nrow(params) - maxParam, "extra rows"))
    }

  ret <- list()
  for (ix in 1:numItems) {
    i <- items[[ix]]
    param <- c()
    if (is.list(params)) {
      param <- params[[ix]]
    } else {
      param <- params[,ix]  # item parameters are in columns
    }

    if (length(param) < rpf.numParam(i)) {
      stop(paste("Item",class(i),"needs",rpf.numParam(i),
                 "parameters but only",length(param),"given"))
    }

    cols <- design[,ix]
    cols <- cols[!is.na(cols)]
    i.theta <- theta[cols,,drop=FALSE]
    P <- rpf.prob(i, param[1:rpf.numParam(i)], i.theta)
#    if (any(is.na(P))) stop(paste("Item", i@spec, "with param", param," produced NAs"))
    ret1 <- apply(P, 2, sample, x=1:i@outcomes, size=1, replace=F)
    labels <- 1:i@outcomes
    if (!missing(grp) && !is.null(grp$data)) labels <- levels(grp$data[1, name[ix]])
    ret1 <- factor(ret1, levels=1:i@outcomes, ordered=TRUE, labels=labels)
    attr(ret1, 'mxFactor') <- TRUE  # for OpenMx
    ret[[ix]] <- ret1
  }
  ret <- as.data.frame(ret, optional=TRUE)
  if (is.null(name)) name <- paste(prefix,1:numItems,sep="")
  colnames(ret) <- name
  if (mcar > 0) {
      size <- prod(dim(ret))
      mask <- rep(FALSE, size)
      mask[sample.int(size, size * mcar)] <- TRUE
      shaped.mask <- array(mask, dim=dim(ret))
      ret[shaped.mask] <- NA
  }
  return(ret)
}