Reputation: 179
We can get element at 2nd row, 4th column as
iris[2,4]
How to do the same if I have a vector/matrix of the slicing elements. ie can i get any of the following to give the same output as iris[2,4] ? (Or anything similar, without creating any temporary variables)
a = c(2,4)
b = matrix(c(2,4), nrow=1)
c = list(2,4)
iris[a]
iris[b]
iris[c]
Upvotes: 1
Views: 2805
Reputation: 8846
The value is coerced to character because you're using a matrix
method for subsetting, and one of the columns is of class character.
We can circumvent this in two ways. Either we remove the character column beforehand,
v <- c(2, 4)
m <- matrix(c(2, 4), nrow=1)
l <- list(2, 4)
iris[,-5][t(v)]
# [1] 0.2
iris[,-5][m]
# [1] 0.2
iris[,-5][do.call(cbind, l)]
# [1] 0.2
or we use a list
method for subsetting. (iris
is a data.frame
, so both are applicable)
iris[[rev(v)]]
# [1] 0.2
iris[[rev(c(m))]]
# [1] 0.2
iris[[rev(unlist(l))]]
# [1] 0.2
I know it's been years, but I just wanted to reiterate that rev()
is necessary when using the output from match(, arr.ind=TRUE)
mat <- matrix(c(1:9, 1:7), 4)
(dtf <- as.data.frame(mat))
# V1 V2 V3 V4
# 1 1 5 9 4
# 2 2 6 1 5
# 3 3 7 2 6
# 4 4 8 3 7
(id <- which(mat == 8, arr.ind=TRUE))
# row col
# [1,] 4 2
mat[id]
# [1] 8
dtf[[rev(id)]] # Traverse as list; first column, then row
# [1] 8
dtf[id] # Indexing as matrix; first row, then column
# [1] 8
dtf[[id]] # Does not work
# Error in as.matrix(x)[[i]] :
# attempt to select more than one element in vectorIndex
dtf[[c(id)]] # Wrong index
# [1] 5
### Multiple matches
(id <- which(mat == 2, arr.ind=TRUE))
# row col
# [1,] 2 1
# [2,] 3 3
mat[id]
# [1] 2 2
dtf[id]
# [1] 2 2
dtf[[rev(id)]] # Does not work any more
# Error in .subset2(x, i, exact = exact) :
# recursive indexing failed at level 2
### Why traversing a data.frame as list can be useful
(dtf$V1 <- as.character(dtf$V1))
# [1] "1" "2" "3" "4"
(id <- which(dtf == 1, arr.ind=TRUE)) # Will match both characters and numerics
# row col
# [1,] 1 1
# [2,] 2 3
dtf[id] # Returns both as character
# [1] "1" "1"
l <- lapply(data.frame(t(id)),
function(x) {
dtf[[rev(x)]]
}
)
sapply(l, class) # Retains classes
# X1 X2
# "character" "integer"
Upvotes: 3