Closed friendly closed 2 months ago
OK -- I've now moved the rbind.latexMatrix()
, cbind.latexMatrix()
, and [.latexMatrix()
methods and examples to R/latexMatrix.R
.
I hope that you didn't end up losing work.
Great, thanks John. I've uploaded a dev/addPartitions.R
function to add partitioning lines as a complimentary helper. Not sure if more flexibly should be added, such as \multicolumn{.}
and \cline{.}
for partial partitioning, but it's a start.
Hmm. My last emailed response doesn't seem to have made it here.
I coincidentally added the ability to show partition lines to print.LatexMethod()
via hline
and vline
arguments. That's now in dev/print.LatexMethod.R
, with a couple of examples.
I wouldn't, of course, have done that if I knew you were working on something similar! I think I've had enough for the night, so will look at what you did tomorrow.
Hi John,
No problem at all. I wasn't sure if we wanted to go down the LaTeX array
route but I think that's more kosher for vertical lines.
Note that to behave well with Eqn()
the return should be an invisible character vector, otherwise the object will be printed twice, which is why addPartition()
just returned the modified object instead of trying to print. Alternatively, the object returned could have a flag added to it such as x$cat <- FALSE
so that Eqn()
knows not to reprint the returned object since it was already cat-ed.
I took at look at your solution. I think that there's a problem with altering the elements in the "latexMatrix"
object, which then couldn't be used in further computation.
On the other hand, one could add a $partition
slot to the object with contents like list(h=c(2, 4), v=c(3, 5))
and which defaults to NULL
. This could be done by latexMatrix()
directly or by a separate function like addParition()
. The @matrix
slot could be modified accordingly without changing the print()
method, so Eqn()
should still work.
In addition, I didn't realize that one could add \hline
to the beginning of the next line rather than to the end of the current line to show a partitioning line in a matrix. I should be able to greatly simplify my code doing that.
Assuming that this plan is sound, I should have time today to try to work everything out along the lines I just suggested.
Interesting, I hadn't considered carrying the partitions through to other operations. That makes sense for some matrix operators (addition, Hadamard, Kronecker), but for others, like multiplication, I'd have to think more clearly about what it would mean or if it's even useful as the resulting row/col dimensions change.
@john-d-fox Is it OK for me to edit the documentation for latexMatrixOperations
or should I wait.
What I did before was mainly a bit of extra text in the @description
+ a few typos I found.
( I had also indented continued lines under @param
for readability.)
#' Various Functions and Operators for \code{l"atexMatrix"} Objects
#'
#' @description
#'
#' These operators and functions provide for LaTeX representations of
#' symbolic and numeric matrix arithmetic and computations.
#' They provide reasonable means to compose meaningful matrix equations
#' in LaTeX far easier than doing this manually matrix by matrix.
#'
#' The following operators and functions are documented here:
Actually, I wasn't suggesting using the partitions in further operations (as you say, that doesn't necessarily make sense), just that your approach of modifying the elements of a matrix would interfere with, e.g., adding, multiplying, etc., matrices.
Also, after further thought, the plan I proposed is too elaborate. I think that I can do what's needed more simply.
On 2024-08-29 10:20 a.m., Phil Chalmers wrote:
Caution: External email.
Interesting, I hadn't considered carrying the partitions through to other operations. That makes sense for some matrix operators (addition, Hadamard, Kronecker), but for others, like multiplication, I'd have to think more clearly about what it would mean or if it's even useful as the resulting row/col dimensions change.
— Reply to this email directly, view it on GitHub <https://github.com/ friendly/matlib/issues/58#issuecomment-2317843548>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ ADLSAQU6D5532X36FRKJ35TZT4U2VAVCNFSM6AAAAABM42L7RCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMJXHA2DGNJUHA>. You are receiving this because you were mentioned.Message ID: <friendly/ @.***>
I added some stuff on partitioned matrices to the vignette. [
indexing and r/c-bind
work nicely here.
Maybe this is enough? I like the result of addPartitions()
, but not at the expense of making "latexMatrix" objects
more complicated.
> addPartitions(M, row=c(2,4), col = c(2,4))
\begin{pmatrix}
\beta_{11} & \beta_{12} \bigm| & \beta_{13} & \beta_{14} \bigm| & \beta_{15} & \beta_{16} \\
\beta_{21} & \beta_{22} \bigm| & \beta_{23} & \beta_{24} \bigm| & \beta_{25} & \beta_{26} \\
\hline \beta_{31} & \beta_{32} \bigm| & \beta_{33} & \beta_{34} \bigm| & \beta_{35} & \beta_{36} \\
\beta_{41} & \beta_{42} \bigm| & \beta_{43} & \beta_{44} \bigm| & \beta_{45} & \beta_{46} \\
\hline \beta_{51} & \beta_{52} \bigm| & \beta_{53} & \beta_{54} \bigm| & \beta_{55} & \beta_{56} \\
\end{pmatrix}
Ah, I see what you mean now; thanks for clarifying. Agreed, my approach would needlessly break too much, and I like the idea of adding the partitions as a separate object element. Should it make sense to apply some logic to the operations with partitions down the road we could do so.
You might want to hold off on partitioned matrices for now since this is in flux.
I just added dev/partition.R with a partition() function that alters just the printed representation of the object, and is, e.g., used as
X <- latexMatrix(nrow=5, ncol=6) partition(X, rows=c(2, 4), columns=c(3, 5))
\begin{pmatrix} \begin{array}{c c c | c c | c} x{11} & x{12} & x{13} & x{14} & x{15} & x{16}\ x{21} & x{22} & x{23} & x{24} & x{25} & x{26}\ \hline x{31} & x{32} & x{33} & x{34} & x{35} & x{36}\ x{41} & x{42} & x{43} & x{44} & x{45} & x{46}\ \hline x{51} & x{52} & x{53} & x{54} & x{55} & x{56}\ \end{array} \end{pmatrix}
If this proves sound (and it would be a good idea to try it out to test it some more), then I would add it to R/latexMatrix.R
On 2024-08-29 11:45 a.m., Michael Friendly wrote:
Caution: External email.
I added some stuff on partitioned matrices to the vignette. |[| indexing and |r/c-bind| work nicely here.
Maybe this is enough? I like the result of |addPartitions()|, but not at the expense of making "latexMatrix" objects more complicated.
|> addPartitions(M, row=c(2,4), col = c(2,4)) \begin{pmatrix} \beta{11} & \beta{12} \bigm| & \beta{13} & \beta{14} \bigm| & \beta{15} & \beta{16} \ \beta{21} & \beta{22} \bigm| & \beta{23} & \beta{24} \bigm| & \beta{25} & \beta{26} \ \hline \beta{31} & \beta{32} \bigm| & \beta{33} & \beta{34} \bigm| & \beta{35} & \beta{36} \ \beta{41} & \beta{42} \bigm| & \beta{43} & \beta{44} \bigm| & \beta{45} & \beta{46} \ \hline \beta{51} & \beta{52} \bigm| & \beta{53} & \beta{54} \bigm| & \beta{55} & \beta{56} \ \end{pmatrix} |
image.png (view on web) <https://github.com/user-attachments/assets/ ecd4fe9e-1d4c-49f8-9088-5f77dce5fa80>
— Reply to this email directly, view it on GitHub <https://github.com/ friendly/matlib/issues/58#issuecomment-2318192330>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ ADLSAQWTMBV4WYAS26TEVX3ZT46ZNAVCNFSM6AAAAABM42L7RCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMJYGE4TEMZTGA>. You are receiving this because you were mentioned.Message ID: <friendly/ @.***>
I think that adding the partition information to the object is more elaborate than necessary. The partition() function I just added in dev/partition.R simply modifies the $matrix slot of the "latexMatrix" object and so affects only the printed representation of the object.
On 2024-08-29 11:47 a.m., Phil Chalmers wrote:
Caution: External email.
Ah, I see what you mean now; thanks for clarifying. Agreed, my approach would needlessly break too much, and I like the idea of adding the partitions as a separate object element. Should it make sense to apply some logic to the operations with partitions down the road we could do so.
— Reply to this email directly, view it on GitHub <https://github.com/ friendly/matlib/issues/58#issuecomment-2318198664>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ ADLSAQS6O7PV2YWQWGG5CIDZT47CXAVCNFSM6AAAAABM42L7RCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMJYGE4TQNRWGQ>. You are receiving this because you were mentioned.Message ID: <friendly/ @.***>
Your partition()
function looks great, and testifies to the elegance of this design with wrapper, body, etc.
I'll test it out some more.
I did some further testing and then added partition()
(now a generic function with a "latexMatrix"
method) to R/latexMatrix.R
; I updated the Roxygen/.Rd.
markup accordingly, including an example.
I wonder whether this "issue" has gotten too long!
This issue has certainly grown past its original intent... and, I honestly can't tell if it has been resolved. Does the simplify
portion address this issue (if I recall there was an issue with trailing -1
s, though that may have been patched)? If so, I vote to close. Many of the new functions will require a suite of testing anyway, so any remaining issues should be caught around that time.
An interesting edge-case with matrix indexing:
> A <- matrix(1:4, nrow =2) |> latexMatrix()
> A[1,1]
\begin{pmatrix}
1 \\
\end{pmatrix}
This is certainly OK, in that it renders as a 1x1 pmatrix: (1). Would we ever want it otherwise, i.e., just "1"?
I don't think that we should always make 1 x 1 matrices into "scalars" but in this case I think that it makes sense to return the contents of the single element as a scalar (i.e., one-element R character vector).
On 2024-08-30 5:47 p.m., Michael Friendly wrote:
Caution: External email.
An interesting edge-case with matrix indexing:
|> A <- matrix(1:4, nrow =2) |> latexMatrix() > A[1,1] \begin{pmatrix} 1 \ \end{pmatrix} |
This is certainly OK, in that it renders as a 1x1 pmatrix: (1). Would we ever want it otherwise, i.e., just "1"?
— Reply to this email directly, view it on GitHub <https://github.com/ friendly/matlib/issues/58#issuecomment-2322382905>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ ADLSAQULY4ZWCZ5MI52GHYDZUDR7RAVCNFSM6AAAAABM42L7RCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMRSGM4DEOJQGU>. You are receiving this because you were mentioned.Message ID: <friendly/ @.***>
An as.vector()
function would IMO be the best way to do this. We could do something like A[1,1,drop=TRUE]
, but that's rather against the drop
convention.
I wrote sections on Partitioned matrices and Kronecker products in the vignette. Take a look, make edits or suggestions, etc.
I'm looking at the pkgdown
documentation for latexMatrix
, http://friendly.github.io/matlib/reference/latexMatrix.html
Aside from the fact that some generated equations aren't rendered, I note:
partition()
doesn't appear, nor is it in the Reference index. I can't see why this is.rbind()
has a default deparse.level = 1
but cbind()
does notMy emailed comments don't seem to have made it here.
(1) I can make the deparse.level
argument to the rbind()
and cbind()
methods consistent. The argument is ignored in any event.
(2) I can alter the indexing method so that it returns a one-element character vector when a single element is selected.
Unless someone objects, I'll go ahead and do this. I'll wait awhile in case someone else is working on latexMatrix.R.
With respect to the vignette. I think that it would be desirable to add partition lines to the final Kronecker-product example. Also, it is probably worth mentioning that partition()
can show more than one horizontal and vertical partition line (or no line at all).
Oh, one more thing. With respect to returning a single element as a "scalar": Should this always happen? If not, Phil seems suggest that we add an as.vector.latexMatrix()
method rather than a drop
argument to [.latexMatrix
, but it's unclear to me what theas.vector()
method would do with anything but a 1 x 1 matrix. I think it makes more sense to add drop
with FALSE
as the default (even though other [ methods AFAIK have TRUE
as the default).
As a thought, the ambiguity would be removed if bracket indexing always returned the matrix elements rather than a latexMatrix
. I imagine if one is using [,]
there's reason to have direct access to the elements, after which the result could be wrapped back via A[i,j] |> latexMatrix()
. That way empty row/col indices have the same behaviour on the returned vectors.
That approach loses the LaTeX matrix environment if it's not pmatrix
. If you want the character sub-matrix, why not just use, e.g., getBody(X[1:2, 3:4])
or getBody(X)[1:2, 3:4]
?
No disagreement on that, though by the same token why not use the getBody() logic to get the scalar element?
Perhaps instead of A[,] with a drop logical a A[,,body=TRUE] could be used?
--- Sent from my mobile phone. Please excuse any tpyos or unusual autocorrect-ships
On Sat, Aug 31, 2024, 12:00 PM John Fox @.***> wrote:
That approach loses the LaTeX matrix environment if it's not pmatrix. If you want the character sub-matrix, why not just use, e.g., getBody(X[1:2, 3:4]) or getBody(X)[1:2, 3:4]?
— Reply to this email directly, view it on GitHub https://github.com/friendly/matlib/issues/58#issuecomment-2322944659, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJXEYDFP6GOVZ6STIPG4A3ZUHSCFAVCNFSM6AAAAABM42L7RCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMRSHE2DINRVHE . You are receiving this because you commented.Message ID: @.***>
Too many things in this thread now!
(1) Re: deparse.level
: Just make consistent with base::rbind(..., deparse.level=1)
(2) Re: indexing: Just use drop = FALSE
(default). The 1x1 case was just a bit surprising at first, but it is perfectly consistent with other uses of [
that yield a latexMatrix
object.
(3) Re: the Kronecker product example -- I'll add the partition lines.
(4) I won't touch latexMatrix.R
(5) Any idea about:
I'm looking at the
pkgdown
documentation forlatexMatrix
, http://friendly.github.io/matlib/reference/latexMatrix.html* `partition()` doesn't appear, nor is it in the Reference index. I can't see why this is.
"Too many things in this thread now!" Indeed. I hoped we could close the thread and open another (or other) more specific thread(s) as necessary.
With respect to:
(1) I've gone with deparse.level
(no -1
) in both cases since the argument is ignored. The value -1
is passed by the generic in any event. I thought that providing the default value for these methods would be potentially confusing to the user given that the argument is ignored. Feel free to change this to deparse.level=1
in both cases if you wish.
(2) Yes, I had drop=FALSE
as the default, and it applied only to the 1 x 1 case, since it's necessary that drop=FALSE
when a "latexMatrix"
object is returned. Phil's suggestion of instead having a body
argument seems ambiguous to me, inasmuch as getBody(X[1, 1])
and getBody(X)[1, 1]
produce different results -- the first a 1 x 1 character matrix and the second a 1-element character vector. Which would be intended by body=TRUE
? This has gotten too complicated for me. I reverted the changes here that I made locally and have just left [.latexMatrix()
as-is. In the probably unusual case where one wants a single character value, just use, e.g., getBody(X)[1, 1]
. Please feel free to change [.latexMatrix()
to handle the 1 x 1 case more flexibly if you wish.
(3) Thank you.
(4) I committed the small change I made to the deparse.level
arg.
(5) I have no idea. More generally, I often find the behaviour of Roxygen and GitHub actions mysterious.
Sorry -- I accidentally closed and then reopened this issue. I do think that we should close it, but I didn't mean to preempt the decision...
Closing now...
In my vignette example of linear hypotheses, the following generates the C & B matrices:
which generates a correct result, but one that is hard to look at:
and looks like this:
Trivial simplification of this could:
1 \cdot
Just removing the 0 * terms:
Is this possible? An operator function like
%*%
can't take other arguments, but could it handle an option in the environment?