You are here

mxPath unexpected behavior with all = TRUE

8 posts / 0 new
Last post
mspiegel's picture
Offline
Joined: 07/31/2009 - 15:24
mxPath unexpected behavior with all = TRUE

Imagine I want to create the following model:

I try creating this model fragment using the following R code:

lVars 

But this code generates the model:

What happened here? The explanation: When the mxPath() function is called with all = TRUE, it will generate n x m paths, where n is the length of 'from' argument and 'm' is the length of the 'to' argument. Keep in mind that when a path is created, it will clobber any existing path that has the same 'from', 'to', and number of arrows. In the case of symmetric paths, the 'from' and 'to' arguments can be switched with impunity. So the following paths are created:

From To Label
a a p1
a b p2
b a p3
b b p1

This is a bug, right? The expected behavior when all = TRUE and arrows = 2 is not to clobber 1/2 of the generated paths. Does anyone have an example where the behavior shown here is the desired behavior?

AttachmentSize
Image icon correct.jpg69.54 KB
Image icon incorrect.jpg69.4 KB
tbates's picture
Offline
Joined: 07/31/2009 - 14:25
"all" is is every-possible,

"all" is is every-possible, so I think this is doing the requested behaviour, but no-one would desire it :-)

So I think you are requesting and getting
from a to a
from a to b
from b to a
from b to b
When the third path is not wanted, and shifts your labels.

I accomplish this using

lVars = c('a', 'b');
model = mxModel('model', type = 'RAM',
	latentVars = lVars,
	mxPath(from = lVars, arrows = 2, labels = paste(lVars,"_var", sep="")), # variances
	mxPath(from = lVars, to = lVars, arrows = 2,  all = T, excludeself=T, labels = 'p2') # covariances
)
tbates's picture
Offline
Joined: 07/31/2009 - 14:25
test case from the examples
data(HS.fake.data)  #load the data
names(HS.fake.data)
Spatial   

Should look like this:

@labels
         visual cubes paper numeric series arithmet general paragrap sentence vis    math   text  
...
vis      NA     NA    NA    NA      NA     NA       NA      NA       NA       NA     "cov1" "cov2"
math     NA     NA    NA    NA      NA     NA       NA      NA       NA       "cov1" NA     "cov3"
text     NA     NA    NA    NA      NA     NA       NA      NA       NA       "cov2" "cov3" NA   

not this

@labels
         visual cubes paper numeric series arithmet general paragrap sentence vis    math   text  
...
vis      NA     NA    NA    NA      NA     NA       NA      NA       NA       NA     "cov1" "cov1"
math     NA     NA    NA    NA      NA     NA       NA      NA       NA       "cov1" NA     "cov2"
text     NA     NA    NA    NA      NA     NA       NA      NA       NA       "cov1" "cov2" NA   
Ryne's picture
Offline
Joined: 07/31/2009 - 15:12
So this should be smarter,

So this should be smarter, but we run the risk of having different functionality for 1 and 2 headed arrows. One way to restate what you're pointing out is that when arrows=2, mxPath populates a symmetric matrix, so our usual tricks for populating symmetric matrices should work. The difference between mxPath and mxMatrix is that mxMatrix requires that the vector of labels be a multiple of the number of elements in the matrix, whereas mxPath allows you to supply 3 labels for four paths.

This is a bigger discussion, and one I would have thought we'd have had before. I think at least a warning is warranted, depending on whether we're telling people that they gave 3 labels for 4 paths or telling them that they assigned the same parameter two different labels.

Just as a reminder, this is what we do if someone tried to pull Mike's dual assignment of the a b covariance in a matrix:

mxMatrix("Symm", 2, 2, labels=letters[1:4])
Error: Labels matrix of symmetric matrix 'untitled36' is not symmetric!

mspiegel's picture
Offline
Joined: 07/31/2009 - 15:24
I advocate that the behavior

I advocate that the behavior is a bug. If 'arrows' is '1' and 'all' is 'TRUE', then the number of paths should be |to| x |from| for all cases.

If 'arrows' is '2' and 'all' is 'TRUE', then the number of paths should be |to| x |from| if and only if 'to' and 'from' contain non-overlapping elements. If 'to' and 'from' contain overlapping elements, then the mxPath() function should not generate duplicate paths that overwrite old paths.

tbrick's picture
Offline
Joined: 07/31/2009 - 15:10
We need to think about

We need to think about consistency with other functions, too.

paste() doesn't have an all=TRUE flag, but we're in the process of implementing mxPaste() that does. We will want the behavior of mxPaste() to be consistent with mxPath() for any value of 'arrows'.

That is, we want to be able to do mxPath(from=latents, to=latents, arrows=x, all=TRUE, labels=mxPaste(latentNames, latentNames, all=TRUE)) to work regardless of whether x is 1 or 2.

There's also the complexity argument--at least with the current setup, the behavior is always the same. In this set up, what happens if from and to are overlapping but not identical? What if there are duplicates in from= or to=? We at least need a simple guiding rule.

The prospect of creating a path then immediately klobbering it doesn't seem right either--if we can come up with an easy guiding rule, I think I can get behind the change in semantics. What is the easy way to automatically generate labels for mxPath(from=vars, arrows=2, all=TRUE)?

What about mxPath(from=vars1, to=vars2, arrows=2, all=TRUE) if vars1 and vars2 are overlapping but not identical? (When I ran this by Mike Spiegel, he validly asked "when would anyone do that?" I don't have an answer, so if anybody does, please let me know.)

Either way, I tend to agree with Ryne--it makes sense to at least throw a warning if people provide a the number of elements being labeled that isn't a clean multiple of the number of labels. Yes, people will probably ignore it. But at least we tried. This warning-throwing behavior for mismatched numbers of values is pretty common in R.

tbates's picture
Offline
Joined: 07/31/2009 - 14:25
guiding rule: call never stomps on something it made

I think the guiding rule should be that the function never stomps on something that this call to it created.

That would mean
1. accumulating a list of from-to paths
2. removing duplicates (including mirror images)
3. then creating them, using the provided labels.

Only if the final list doesn't match the label length should a warning be thrown.

This way from and too lists can overlap partly or completely and you always get one connection from everthing on the left to everything on the right, which is a nice intention-oriented interpretation of "ALL" as "all unique combinations".

mspiegel's picture
Offline
Joined: 07/31/2009 - 15:24
Update: the following code

Update: the following code snippet now works in the source code repository, as of revision 1738. This functionality will be available in OpenMx 1.2.

lVars 
Log in or register to post comments