Элегантная индексация до конца вектора/матрицы
Можно ли в R сказать - мне нужны все индексы с позиции i
до конца вектора/матрицы?
Скажем, мне нужна подматрица из третьей колонки. В настоящее время я знаю только так:
A = matrix(rep(1:8, each = 5), nrow = 5) # just generate some example matrix...
A[,3:dim(A)[2]] # get submatrix from 3rd column onwards
Но мне действительно нужно написать этот уродливый dim(A)[2]
? Разве нет элегантного способа сказать "от третьей колонки вперед"? Что-то вроде A[,3:]
? (или A[,3:...]
)?
Ответы
Ответ 1
Иногда вам проще сказать R, что вы не хотите. Другими словами, исключить столбцы из матрицы, используя отрицательную индексацию:
Вот два альтернативных способа, которые дают одинаковые результаты:
A[, -(1:2)]
A[, -seq_len(2)]
Результаты:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3 4 5 6 7 8
[2,] 3 4 5 6 7 8
[3,] 3 4 5 6 7 8
[4,] 3 4 5 6 7 8
[5,] 3 4 5 6 7 8
Но ответьте на свой вопрос: "ncol
), чтобы найти количество столбцов. (Аналогично, существует nrow
, чтобы найти количество строк.)
A[, 3:ncol(A)]
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3 4 5 6 7 8
[2,] 3 4 5 6 7 8
[3,] 3 4 5 6 7 8
[4,] 3 4 5 6 7 8
[5,] 3 4 5 6 7 8
Ответ 2
Для строк (не столбцов в соответствии с вашим примером) можно использовать head()
и tail()
.
A <- matrix(rep(1:8, each = 5), nrow = 5)
tail(A, 3)
почти совпадает с
A[3:dim(A)[1],]
(напечатанные имена/индексы отличаются друг от друга).
Они также работают для векторов и фреймов данных:
> tail(1:10, 4)
[1] 7 8 9 10
> tail(data.frame(A = 1:5, B = 1:5), 3)
A B
3 3 3
4 4 4
5 5 5
Для версий столбцов вы можете адаптировать tail()
, но это немного сложнее. Интересно, может ли здесь быть полезным NROW()
и NCOL()
, а не dim()
?:
> A[, 3:NCOL(A)]
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3 4 5 6 7 8
[2,] 3 4 5 6 7 8
[3,] 3 4 5 6 7 8
[4,] 3 4 5 6 7 8
[5,] 3 4 5 6 7 8
Или переверните это на голове и вместо того, чтобы просить R о вещах, попросите его вместо этого отказаться. Вот функция, которая инкапсулирует это:
give <- function(x, i, dimen = 1L) {
ind <- seq_len(i-1)
if(isTRUE(all.equal(dimen, 1L))) { ## rows
out <- x[-ind, ]
} else if(isTRUE(all.equal(dimen, 2L))) { ## cols
out <- x[, -ind]
} else {
stop("Only for 2d objects")
}
out
}
> give(A, 3)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 2 3 4 5 6 7 8
[2,] 1 2 3 4 5 6 7 8
[3,] 1 2 3 4 5 6 7 8
> give(A, 3, dimen = 2)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3 4 5 6 7 8
[2,] 3 4 5 6 7 8
[3,] 3 4 5 6 7 8
[4,] 3 4 5 6 7 8
[5,] 3 4 5 6 7 8