Formal restatement of the problem
Given the integers i,j
and the matrix/data.frame x
, find the m
such that:
x[i,m]; x[m,j]; x[m,m]
are identical resp. to:
x[i,]; x[,j]; x[,]
This should of course apply also to replacements, i.e. for:
x[*] = value
and with the syntax `[`
and `[<-`
or the related do.call
.
Investigation of the problem
If you are not interested to know what is under the hood, you can go straight to the proposed solution.
Since `[`
and `[<-`
are functions, m
should be considered as a missing value for the arguments i, j
. Therefore one should create an "artificial" missing value.
What happens upon inspection of actual missing values in a function?
f=function(i,j){
cat ('A) '); print(match.call())
cat ('B) '); print(sys.call())
cat ('C)\n'); print(as.list(sys.call()))
}
When using a comma without a preceding argument, we get:
f(,2)
#A) f(j = 2)
#B) f(, 2)
#C)
#[[1]]
#f
#
#[[2]]
#
#
#[[3]]
#[1] 2
The second element of the sys.call
list seems empty! So we try to capture this value:
f=function(a,b) as.list(sys.call())[[2]]
m=f(,)
and:
m
Error: argument "m" is missing, with no default
...never an error was so welcomed.
Proposed solution
Set:
m=(function(a,b) as.list(sys.call())[[2]])(,)
m
is now an artificial missing value. It operates like the empty space near the comma when subsetting. In fact:
x=matrix(1:12, ncol=3)
x[m,m]
# [,1] [,2] [,3]
#[1,] 1 5 9
#[2,] 2 6 10
#[3,] 3 7 11
#[4,] 4 8 12
x[1, m ]
#[1] 1 5 9
x[m, 1 ]
#[1] 1 2 3 4
So far, while more formal, this method does not offer more than the recycling trickery x[T,T]
, x[1,T]
, x[T,1]
. But, when the workaround does not work:
x=data.frame(x)
x[T,4:5]=0
#Error in `*tmp*`[[j]] : subscript out of bounds
the artificial missing value works:
x[m,4:5]=0
x
# X1 X2 X3 V4 V5
#1 1 5 9 0 0
#2 2 6 10 0 0
#3 3 7 11 0 0
#4 4 8 12 0 0