Gostaria de preencher uma matriz por linha com base em uma função que fornece a seq() de um número seq(1) 1 seq(2) 1 2 e assim por diante
matrixinp = matrix(data=NA, nrow=6, ncol=6)
> print(matrixinp)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] NA NA NA NA NA NA
[2,] NA NA NA NA NA NA
[3,] NA NA NA NA NA NA
[4,] NA NA NA NA NA NA
[5,] NA NA NA NA NA NA
[6,] NA NA NA NA NA NA
# display matrix
print(matrixinp)
# fill the elements with some
# 90 in a matrix
for (i in 1:6){
aaa<-seq(i)
print(aaa)
for(j in 1:6){
matrixinp[j,] = aaa
}
}
Isso me deu isto:
> print(matrixinp)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 1 2 3
[2,] 1 2 3 1 2 3
[3,] 1 2 3 1 2 3
[4,] 1 2 3 1 2 3
[5,] 1 2 3 1 2 3
[6,] 1 2 3 1 2 3
mas eu gostaria disto:
> print(matrixinp)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 NA NA NA NA NA
[2,] 1 2 NA NA NA NA
[3,] 1 2 3 NA NA NA
[4,] 1 2 3 4 NA NA
[5,] 1 2 3 4 5 NA
[6,] 1 2 3 4 5 6
Aposto que uma linha pode resolver isso, R é uma linguagem vetorizada.
Criado em 2024-09-17 com reprex v2.1.0
Espere, eu ganhei a aposta.
O truque é saber que as matrizes de R são colunas principais, portanto, com a matriz de índice,
lower.tri
os valores irão para os lugares certos.Como uma função:
Você pode tentar
onde
diag(1:6)*NA
produz uma6-by-6
matriz deNA
slower.tri
recupera a parte triangular inferior dem
replace
substitui os valoresm
de acordo com o indicador de máscaraOu, se você quiser manipulações por linha
onde
`length<-`
define os comprimentos para o vetor fornecidodo.call(rbind, ...)
empilha vetores na lista por linhas1) Crie uma matriz diagonal 6x6, preencha-a com os números das colunas e então extraia o triângulo superior.
dando
2) ou com o cachimbo nativo:
3) Defina cc como uma matriz 6x6 com números de colunas como acima e então use a fórmula mostrada.
Você pode tentar o seguinte,
Mantenha a criação inicial da matriz vazia com valores NA. Use um único loop que itere sobre as linhas (1 a 6). Para cada linha i, preenchemos apenas as primeiras i colunas com a sequência seq(i). O restante dos elementos em cada linha permanece NA como definido inicialmente.
Este método garante que cada linha tenha a sequência até seu número de linha, e o restante das partes permaneçam como NA.
Você precisa fazer isso especificamente com um loop e
seq()
?Você poderia criar essa matriz muito facilmente com as habilidades de álgebra matricial do R:
Mas se você quiser entender por que seu loop não estava funcionando:
Quando você executa,
seq(4)
obtém um vetor de comprimento 4c(1,2,3,4)
. Você então tenta atribuí-lo a cada linha dematrixinp
, mas as linhas naquela matriz têm 6 elementos de comprimento. Essa atribuição falhará com o erronumber of items to replace is not a multiple of replacement length
quando você chegar à 4ª iteração do loop.Antes de chegar à 4ª iteração, 6 é um múltiplo de 1, 2 e 3, então, para essas iterações, R preenche a matriz com repetições do seu vetor aaa:
aaa=1
, ele preenche as linhas da matriz comc(1,1,1,1,1,1)
.aaa=c(1,2)
ele preenche as linhas da matriz comc(1,2,1,2,1,2)
.aaa=c(1,2,3)
, ele preenche as linhas da matriz comc(1,2,3,1,2,3)
.É por isso que você tem aquela matriz estranha onde cada linha era 1 2 3 1 2 3 - quando i=3, o loop interno com j atribuído
c(1,2,3,1,2,3)
a cada linha da matriz. Então seu loop parou quando encontrou um erro em i=4, deixando você com a versão i=3 da matriz.Para ajudar o autor da pergunta original a entender, aqui está a frase que escrevi no meu comentário para RuiBarradas:
Este é um código bagunçado e excessivamente complicado por ser bobo e tentar fazer tudo em uma linha. Você geralmente não deve fazer algo assim em código real, pois tornará o código difícil para outras pessoas lerem (ou para você ler quando olhar para ele novamente meses depois). Mas ele demonstra alguns recursos úteis do R, e brincar com coisas assim pode às vezes ajudar a aprender mais sobre R.
Este código é melhor lido de fora para dentro, por exemplo, começando com a função mais externa:
ifelse()
é uma função que verifica se seu primeiro argumento é verdadeiro - se for, ela retorna seu segundo argumento, caso contrário, ela retorna seu terceiro argumento.ifelse(c(T,F,T,F),'A','B')
retornariac('A','B','A','B')
.ifelse()
foilower.tri(matrix(nrow=6,ncol=6),diag=T)
, uma matriz de valores VERDADEIRO/FALSO indicando quais células em uma matriz 6x6 estão no triângulo inferior (incluindo a diagonal como "no triângulo inferior")rep(1,6) %*% t(1:6)
a álgebra matricial da minha outra resposta à sua pergunta, que cria uma matriz com uma coluna só de 1, uma coluna só de 2, etc.Então, esse código verifica para cada célula de uma matriz 6x6 se essa célula está no triângulo inferior. Se estiver, ele pega um valor para essa célula da matriz com uma coluna all-1s, all-2s, etc. Mas se estiver no triângulo superior, ele define essa célula como NA.
E minha segunda frase de efeito:
(!upper.tri(diag(6)) | NA) * (rep(1,6) %*% t(1:6))
(!upper.tri(diag(6)) | NA)
e outra por(rep(1,6) %*% t(1:6))
diag(6)
cria uma matriz 6x6 que tem 1s nas diagonais e 0s em todos os outros lugares. Seu propósito é apenas criar uma matriz 6x6 de uma forma que seja mais curta de escrever do quematrix(nrow=6,ncol=6)
.!upper.tri(diag(6))
usaupper.tri()
naquela matriz para criar uma matriz onde o triângulo superior (excluindo a diagonal) é TRUE e o triângulo inferior é FALSE. Então ele usa!
(o operador "not") para transformar TRUEs em falses e vice-versa.lower.tri(diag(6),diag=T)
para fazer a mesma matriz V/F, mas como isso requer que adiag=T
matriz inclua a diagonal, é mais curto (embora menos legível) para escrever!upper.tri(diag(6))
.(!upper.tri(diag(6)) | NA)
. Pego essa matriz V/F e faço um "ou" lógico com NA. "verdadeiro ou NA" é avaliado como "verdadeiro", enquanto "falso ou NA" é avaliado como NA.