Как сдвинуть каждую строку матрицы в R

У меня есть матрица такого вида:

a b c
d e 0
f 0 0

и я хочу преобразовать его во что-то вроде этого:

a b c
0 d e
0 0 f

Схема переключения такая:

shift by 0 for row 1
shift by 1 for row 2
shift by 2 for row 3
...
shift by n-1 for row n

Конечно, это можно сделать с помощью цикла for. Мне интересно, есть ли лучший способ?


person qed    schedule 10.06.2014    source источник


Ответы (3)


Предполагая, что ваш пример является репрезентативным, т. Е. У вас всегда есть треугольная структура букв и нулей:

mat <- structure(c("a", "d", "f", "b", "e", "0", "c", "0", "0"), 
                 .Dim = c(3L, 3L), .Dimnames = list(NULL, NULL))
res <- matrix(0, nrow(mat), ncol(mat))
res[lower.tri(res, diag=TRUE)] <- t(mat)[t(mat)!="0"]
t(res)
#     [,1] [,2] [,3]
# [1,] "a"  "b"  "c" 
# [2,] "0"  "d"  "e" 
# [3,] "0"  "0"  "f" 
person Roland    schedule 10.06.2014
comment
@CarlWitthoft Конечно. Но он позволяет избежать циклов и должен быть достаточно эффективным, поэтому я решил поделиться этим вариантом. Если ОП показывает нерепрезентативные данные, это не моя вина. - person Roland; 10.06.2014
comment
+1 Я думаю, что это решение очень умное, если выполняются предположения. - person Simon O'Hanlon; 10.06.2014
comment
Чтобы избежать предположений, мы могли бы установить правый нижний треугольник mat равным нулям? - person zx8754; 17.10.2016

Решение head и tail не кажется мне таким же читаемым, как цикл for, и, возможно, даже не таким быстрым. Тем не менее...

t( sapply( 0:(nrow(mat)-1) , function(x) c( tail( mat[x+1,] , x ) , head( mat[x+1,] , nrow(mat)-x ) ) ) )
#     [,1] [,2] [,3]
#[1,] "a"  "b"  "c" 
#[2,] "0"  "d"  "e" 
#[3,] "0"  "0"  "f" 

Версия с for циклом может быть...

n <- nrow(mat)
for( i in 1:n ){
    mat[i,] <- c( tail( mat[i,] , i-1 ) , head( mat[i,] , n-(i-1)  ) )
}
person Simon O'Hanlon    schedule 10.06.2014

Я думаю, это все, что вам нужно:

 mat<-matrix(1:25,5)
 mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25
 for(j in 2:nrow(mat) ) mat[j,]<-mat[j, c(j:ncol(mat),1:(j-1))]
 mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    7   12   17   22    2
[3,]   13   18   23    3    8
[4,]   19   24    4    9   14
[5,]   25    5   10   15   20
person Carl Witthoft    schedule 10.06.2014
comment
Ты уверен? Это не совсем сработало для меня. - person Simon O'Hanlon; 10.06.2014
comment
@SimonO'Hanlon что, мне проверить код? Извините, я вернусь и исправлю это. - person Carl Witthoft; 10.06.2014
comment
Почти! Вы, кажется, переключаетесь влево, а ОП - вправо. - person Simon O'Hanlon; 10.06.2014
comment
@SimonO'Hanlon, ты прав. Но, учитывая его выбор ответа, очевидно, что он фактически хотел подтолкнуть 0 записей. Так что я просто оставлю это как пример для людей, которые хотят заниматься другими вещами :-) - person Carl Witthoft; 10.06.2014