mxMatrix defaults

18 replies [Last post]
tbates's picture
Offline
Joined: 07/31/2009

playing with this

> mxMatrix("Stand", cov2cor(matrix(c(10,9,9,15), nrow=2)), name="Y")
Error in row(tmp) :
a matrix-like object is required as argument to 'row/col'
In addition: Warning messages:
1: In if (is.na(nrow)) { :
the condition has length > 1 and only the first element will be used
2: In if (nrow != ncol) { :
the condition has length > 1 and only the first element will be used

I wonder if mxMatrix could detect that the input was already a matrix, and not require the nrow and ncol numbers to be specified again?

klang's picture
Offline
Joined: 08/23/2009
Just a thought on mean

Just a thought on mean structures. I've been obligated to model the means in every model I've run, even though I'm often only interested in the variance/covariance components. I can understand the motivation for forcing mean modeling as the default (I suppose I should always be modeling the mean structures in my data), but in most the models I run, I'm not intersested in means, and it might be nice to have the option of modeling only the variance/covaiance components.

I only bring this up because I feel I'm not the only one in this boat. Most of the models I see other analysts running are devoid of mean models as well, and no other program I've worked with forces mean modeling as its default, so I fear that it may turn off some potential users.

I don't know if it's to late in the game to do address this issue, or if anyone else feels it should be addressed at all, but I thought I'd bring it up and see what others are thinking.

Steve's picture
Offline
Joined: 07/30/2009
If you wish to just do

If you wish to just do covariance modeling, then you can just pass covariances to mxData as shown in the example on the front page of the website.

But if you want to run FIML, a model for the means is required. Sorry, but that's the nature of the beast.

There will soon be a slight change to the syntax in order to make this a bit easier for mxPath users. It won't be in Monday's (8/31) release (0.1.3-xxx), but it will likely be in the next release after that. Let us know if you feel it helps.

tbates's picture
Offline
Joined: 07/31/2009
Default labels? base-name

Default labels? base-name plus row and column would be fine.

I think that almost all cells of a matrix will be labeled... but they default to no label.

I guess this can be done with paste()... but it again raises the entry for users, increases user-code complexity. A function would be ok, but that decreases portability.

So it would be very useful if something like labels = "a..." was equivalent to:
labels= c(
"a11", "a12", "a13",
"a21", "a22", "a23",
"a31", "a32", "a33")

i.e., "..." as a shorthand for "label based on this".

Ryne's picture
Offline
Joined: 07/31/2009
If we're allowing users to

If we're allowing users to constrain parameters to equality by giving them the same label, this will lead to some problems. If we automatically generate labels, we have the potential to automatically and accidentally constrain things to equality.

Even if we wanted to do this, we'd have to work out nomenclature. In your example, a111 could mean element 1,1 of matrix a1, or either elements 11,1 or 1,11 in matrix a. We also have to deal with multiple models; copying a matrix with default labels for use in two models currently has no equality expectations (default labels are NA). Your proposal would create equalities by default.

Labels are completely optional, so I like that they are NA by default. If I want labels, I'll put them in. R's Extract functionality allows for me to pull out elements by row and column anyway.

tbates's picture
Offline
Joined: 07/31/2009
matrix clone like model

matrix clone like model clone...

It would be helpful if mxMatrix allowed this

expMeanMZMatrix = mxMatrix("Full", nrow=1, ncol=nVar*2, 
        values=meanStarts, label=meanLabels, dimnames=list(NULL, selVars), 
         name="expMeanMZ")
expMeanDZMatrix = mxMatrix(expMeanMZMatrix, name="expMeanDZ") 

i.e., if the first parameter is an mxMatrix, then the result is a new matrix differing only in the updated features... in this case the same in all but name

Ryne's picture
Offline
Joined: 07/31/2009
There's one important

There's one important difference between models and matrices: there's nothing in an MxMatrix object that can't be referenced, whereas it is impossible to add new objects to an MxModel simply by using R's Extract referencing. MxMatrix objects are well known entities, as all MxMatrix objects have slots with predetermined ranges of contents (they all have values, labels and free matrices, as well as slots for types and names and such). MxModel objects do not have this property, as they can contain a large collection of named entities.

expMeanMZMatrix <- mxMatrix("Full", nrow=1, ncol=nVar*2, 
    values=meanStarts, label=meanLabels, 
    dimnames=list(NULL, selVars), name="expMeanMZ")
 
expMeanDZMatrix <- expMeanMZMatrix
expMeanDZMatrix$name <- "expMeanDZ"

Don't have the program in front of me, so I apologize of $name is the wrong reference.

mspiegel's picture
Offline
Joined: 07/31/2009
expMeanDZMatrix <-

expMeanDZMatrix <- expMeanMZMatrix
expMeanDZMatrix@name <- "expMeanDZ"

In the svn repository, the matrix print routines now show the "@" symbol to remind the user that S4 object slots are accessed by "@"s.

pdeboeck's picture
Offline
Joined: 08/04/2009
Two suggested changes to

Two suggested changes to mxMatrix:

1) Automatically figure out ncol or nrows from the other information provided. So for example, I had the following:

> U <- mxMatrix( type="Unit", values=rep(1,Number.occasions), ncol=1)
Error in mxMatrix(type = "Unit", values = rep(1, Number.occasions), ncol = 1) : Both nrow and ncol must be specified on a non-square matrix

As the length of values is known, there shouldn't be a need to specify both ncol & nrow.

2) To shorten the code, I've been using arrays for some of my larger and/or more mutable matrices. For example:

A.info <- array(NA,dim=c(8,8,5))
A.info[,,1] <- "F"
A.info[,,2] <- 0

A.info[7,1,] <- c("T", -0.1, "eta1", NA,NA)
A.info[7,2,] <- c("T", 0.0, "zeta1", NA,NA)
A.info[3,8,] <- c("T", 0.0, "gamma1", NA,NA)
A.info[8,4,] <- c("T", -0.1, "eta2", NA,NA)
A.info[8,5,] <- c("T", 0.0, "zeta2", NA,NA)
A.info[6,7,] <- c("T", 0.0, "gamma2", NA,NA)
A.info[3,7,] <- c("F", 1.0, "fixed", NA,NA)
A.info[6,8,] <- c("F", 1.0, "fixed", NA,NA)

This array holds the information for free, values, labels, lbound and ubound. As most of the array is fixed, it is easier (imo) to just specify a handful of elements. Plus, it seems easier to read the information pertaining to a particular element in the matrix.

Instead of having to write:

mxMatrix( type="Full", free=A.info[,,1], labels=A.info[,,3], values=as.numeric(A.info[,,2]),lbound=as.numeric(A.info[,,4]),ubound=as.numeric(A.info[,,5]))

why not an option to say:

mxMatrix( type="Full", completearray=A.info)

The two fold purpose would be to cutdown the mxMatrix command, but also encourage people to not write out every single matrix (i.e., specify an array as above) --- thereby reducing the code and making it easier to read other people's code. The alternative is a page or more of code specifying 5 8x8 matrices in the above example. (I'll be setting bounds in the future, so I'd need all 5 matrices.)

Just some ideas as I've been working with this.

mspiegel's picture
Offline
Joined: 07/31/2009
In regards to comment #1:

In regards to comment #1: whoops, this was an oversight on our part. I'll place a ticket and get a fix on this. It may take a few days to patch it: with 9 matrix types I've noticed that devilish errors can appear if I'm not careful when making changes (although I guess I only need to patch the non-square matrices).

In regards to comment #2: I am impressed by your array notation to simplify the process of matrix creation. Looks great! However, instead of adding a feature to the mxMatrix() function, why don't you add a function to your scripting library which can make this transformation? Feel free to post the function to the forums once you get it tweaked. I think taking care of missing matrices (putting the right defaults) will be the trickiest part. Use ?mxMatrix to match default values of your function with our function, but you probably know that already.

mspiegel's picture
Offline
Joined: 07/31/2009
Added ticket:

Added ticket: http://openmx.psyc.virginia.edu/issue/2009/08/relax-nrow-and-ncol-reguir.... I think the patch applies only to Full matrices, see ticket.

mspiegel's picture
Offline
Joined: 07/31/2009
If mxMatrix() is invoked when

If mxMatrix() is invoked when type = 'Full' AND either nrow or ncol is specified AND (values, free, labels, lbound, ubound) are all either vectors or unspecified AND the length of all specified vectors are identical, then a matrix is created.

mspiegel's picture
Offline
Joined: 07/31/2009
Check ?mxMatrix, the second

Check ?mxMatrix, the second argument to the function is the number of rows. We should probably be more robust on bogus input to the function, but for now it's buyer beware. Try "mxMatrix("Stand", values = cov2cor(matrix(c(10,9,9,15), nrow = 2)), name = 'Y')" it works.

tbates's picture
Offline
Joined: 07/31/2009
Just looking at ?mxMatrix As

Just looking at ?mxMatrix
As this is only ever viewed by people who need help... It would be nice to:
1. Use labels on parameters
2. Use all common parameters? (name = "3*3 symm", byrow=FALSE)
3. Use values that help the user see what is going on
4. Use other common forms: in this case, the lower-only input
5. Show the output

So instead of
s <- mxMatrix(type="Symm", 3, 3,
c(FALSE, TRUE, TRUE, TRUE, FALSE,
TRUE, TRUE, TRUE, FALSE),
c(1, .8, .8, .8, 1, .8, .8, .8, 1),
c(NA, "free1", "free2", "free1", NA,
"free3", "free2", "free3", NA))

How about:
s <- mxMatrix(
type="Symm", ncol=3, byrow= TRUE, name="3*3_symm",
free=c(FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE),
values= c(1, 2, 3, 2, 4, 5, 3, 5, 6),
labels = c(NA, "free1", "free2", "free1", NA, "free3", "free2", "free3", NA)
)

Would be good to include the results, and also a lower-only example

s <- mxMatrix(
	type="Symm", ncol=3, byrow= TRUE, name="3*3_symm",
    free=c(
	FALSE, 
	TRUE, FALSE, 
	TRUE, TRUE, FALSE),
    values= c(
	1, 
	2, 4, 
	3, 5, 6),
    labels = c(
	NA, 
	"free1", NA, 
	"free2", "free3", NA)
)
> s
SymmMatrix '3*3_symm' 
 
Labels matrix:
     [,1]    [,2]    [,3]   
[1,] NA      "free1" "free2"
[2,] "free1" NA      "free3"
[3,] "free2" "free3" NA     
 
Values matrix:
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    4    5
[3,]    3    5    6
 
Free matrix:
      [,1]  [,2]  [,3]
[1,] FALSE  TRUE  TRUE
[2,]  TRUE FALSE  TRUE
[3,]  TRUE  TRUE FALSE

/rant/
Lots of the R documentation has terrible ?help: It's just left to the hapless user to guess that "..." contains critical unmentioned parameters needed to use the function in practice. And the examples often don't get some real task done.
/rant off/

tbates's picture
Offline
Joined: 07/31/2009
Also in mxMatrix help, how

Also in mxMatrix help, how "byrow" applies when only the lower triangle is supplied is not explicitly stated. byrow TRUE for lower is equivalent to byrow=FALSE for upper, so it is important to know which triangle is being treated as the one being filled.

Currently:
"byrow logical. If ‘FALSE’ (default), the ‘values’, ‘free’, ‘labels’, ‘lbound’, and ‘ubound’ matrices are populated by column rather than by row."

I would add:

Note: for symmetrical matrices being passed on one triangle of data, the "byrow" parameter is interpreted as applying to filling the lower triangle.

mspiegel's picture
Offline
Joined: 07/31/2009
As of revision 721, the

As of revision 721, the mxMatrix documentation has a discussion about populating the lower triangle for Symm, Stand, Lower, and Sdiag matrices. Also the examples have been revised.

tbates's picture
Offline
Joined: 07/31/2009
Thanks Mike: Looks good. PS:

Thanks Mike: Looks good.

PS:

> mxVersion()
[1] "0.1.2-708"
> # current version should be 721

mspiegel's picture
Offline
Joined: 07/31/2009
Error checking to nrow and

Error checking to nrow and ncol arguments of mxMatrix() function added in revision 693.

tbates's picture
Offline
Joined: 07/31/2009
thanks Mike...

thanks Mike... followup

mxMatrix("Stand", cov2cor(matrix(c(10,9,9,15), nrow=2)), name="Y")
# Error: 'nrow' argument to mxMatrix must be either NA or a single value.

that might be confusing to the user, because nrow looks like it is a single value,

maybe
# Error: 'nrow' argument must be either NA or a single value. mxMatrix(type,nrow,ncol, free, values, labels, lbound, ubound, byrow, dimnames, name...)

or
# Error: mxMatrix expected argument 2 to be 'nrow': either NA or a single value.

help in time saves 9 (plaintive emails) :-)