# 6/10/04
# per definire un'array, es 2x3x4:
z<-1:(2*3*4)     # riempiamo il vettore con numeri consecutivi
dim(z)<-c(2,3,4) # lo informiamo delle dimensioni
z                # guardiamolo
dim(z)<-c(6,4)   # le dimensioni possono essere cambiate
z                # riguardiamolo
dim(z)<-c(5,4)   # questo comando da' errore in quanto 5x5 !=  2x3x4
 
z <- 0           # attenzione: questo comando non azzera le
                 # componenti, ma ridefinisce z !
                 # [ricominciare da capo..o a ridefinislo]
z <- z-z         # cosi' invece si azzera sicuramente.
                 # Oppure, per accedere simultaneamente a tutte 
                 # le componenti:
z[] <- 0         # pone tutte le compionenti a zero
 
z <- rep(1,6*4)  # crea z con 6x4 '1'
                 # si potevano mettere anche dei NaN: "z <- rep(NaN,6*4)"
dim(z)<-c(6,4)   # fissa le dimensioni
dim(z)<-c(4,6)   # ovviamente la matrice 6x4 non e' la stessa di una 4x6
 
z[1,]            # prima riga
z[,1]            # prima colonna
 
# Index arrays (Sect. 5.3 "An introduction to R")
x<-array(1:20, c(4,5))        # il primo argomento e' la lista di valori
			      # il secondo le dimensioni
i<-array(c(1:3,3:1), c(3,2))  # idem per i
                              # risultato va visto...
> i
     [,1] [,2]
[1,]    1    3                # (1,3)
[2,]    2    2                # (2,2)
[3,]    3    1                # (3,1)
> z[i]
[1] 9 6 3                     # z[1,3], z[2,2], z[3,1]
 
## function array() [Sec. 5.4]
Z<-array(0,c(3,3))            # fa una matrice 3x3 di zeri 
                              # in array(), se la lista di valori e'
			      # inferiore alle dimensioni, essa viene
			      # 'ciclata', altrimenti viene troncata, 
                              # esempi.: 
Z<-array(1:3,c(3,3))
Z<-array(1:2,c(3,3))
Z<-array(1:4,c(3,3))
 
dim(Z)                        # fornisce un vettori con le dimensioni di Z
length(dim(Z))
Z[] <- 2                      # pone a 2 tutti gli elementi
Z <- Z + 1                    # aggiunge 1 a tutti gli elementi
                              # MA 
Z <- 2                        # !!!   resetta Z ****
 
##  5.5 : outer product of two arrays
a <- 1:2
b <- 3:5
c <- a %o% b      # l'outer product da' a_i*b_j
                  #  a[1]*b[1], a[1]*b[2], a[1]*b[3]
                  #  a[2]*b[1], a[2]*b[2], a[2]*b[3]
                  #  a[3]*b[1], a[3]*b[2], a[3]*b[3]
> c
     [,1] [,2] [,3]
[1,]    3    4    5
[2,]    6    8   10
 
# in generale:
c <- outer(a,b,"*")     # per il 'prodotto'
                        # che pero' puo' essere sostituito con altri
     			# operatori: nota la differenza fra
c <- outer(a,b,"-")     # e
c <- outer(b,a,"-")
                        # inoltre accetta, piu' in generale, una
			# funzione al posto dell'operatore:
f<-function(x,y) x^2+y
c <- outer(b,a,f)
> c
     [,1] [,2]
[1,]   10   11
[2,]   17   18
[3,]   26   27
 
# esempio sulla distribuzione dei 10000 determinanti di una matrice
# 2x2, i cui elementi possono assumere valori discreti fra 0 e 9
# [vedi pag. 23, 5.5]
e <-0:9                # valori possibili degli elementi
p <- outer(e,e)        # i 100 possibili prodotti (matrice 10x10)            
d <- outer(p, p, "-")  # le 10000 possibili differenze 
                       # dei prodotti, ovvero i determ (matrice 10x10x10x10)   
dim(p); length(p)      # per verificare
dim(d); length(d) 
fr<-table(d)           # fa una tabella di frequenze dei valori di d
                       # che razza di oggetto e'? -> si ricorda del 
                       # nome 'd' e dei valori, ma apparentemente 
                       # e' un oggetto lungo 163, di dimensione 163
                       #: ECCO: 
names(fr)              # da' le occorrenze di d, viste come nomi
fr                     # da' la frequenza di ciascuna occorrenza
as.numeric(names(fr))  # traduce in numeri le occorrenze (probabilmente
                       # table e' pensata per statistici, per lavorare
                       # anche su attributi non numerici:
# [ provare con 
x<-c("a","b","c","b","c","c","b","c")
table(x)
# ]               OK!
                       # quindi: 
n<-as.numeric(names(fr))
plot(n,fr,type="h")    
                       # ovvero, come sul documento:
plot(as.numeric(names(fr)),fr,type="h",xlab="Determinant",ylab="Frequency")
 
# in outer si puo' usare una funzione qualsiasi: es.
> ff<-function(x1,x2) x1 + 2*x2 + 3
> outer(1:3,1:3,"ff")
     [,1] [,2] [,3]
[1,]    6    8   10
[2,]    7    9   11
[3,]    8   10   12
# e quindi
> one <- function(x1,x2) 1
> outer(1:2,1:2,"one")
     [,1] [,2]
[1,]    1    1
[2,]    1    1
 
##################################################################
# 5.6 permutazione degli indici di un'array.
                     # data 
z<-1:(2*3*4)         # con
dim(z)<-c(2,3,4) 
                     # la funzione aperm() scambia gli indici
                     # le modo indicato dal secondo argomento
w<-aperm(z,c(1,2,3)) # : non fa niente: indici: 1->1, 2->2, 3->3
w<-aperm(z,c(3,2,1)) # : indici 1->3, 2->2, 3->1
w[3,3,2]==z[2,3,3]   # verifica (risultato TRUE)
w[1,3,2]==z[2,3,1]
 
v<-aperm(z,c(2,3,1)) # rotazione ciclica degli indici
v[2,3,1]==z[1,2,3]   # verifica
v[3,4,2]==z[2,3,4]
 
# nel caso di array bidimensionali, ovvero matrici:
dim(z)<-c(6,4)
aperm(z,c(2,1))      # corrisponde a fare la trasposta, operazione che
                     # si puo' anche fare con t()
aperm(z,c(2,1))==t(z)# verifica
 
 
# 5.7 matrici, ovvero array 2x2
A<-array(1:6,c(2,3)
B<-array(1,c(2,3))
 
# alternativa
A<-matrix(1:6,2,3)
B<-matrix(1,2,3)   # e quindi per creare una matrice vuota 
                   # (ovvero piena di NA):
matrix(,2,3)
 
# operazioni elemento ad elemento: 
A+B
A-B
A*B   # etc.
 
# prodotto di matrici: %*%
A%*%B     # da' errore in quanto non sono matrici quadrate
 
> B%*%t(A)
     [,1] [,2]
[1,]    9   12
[2,]    9   12
 
> t(A)%*%B
     [,1] [,2] [,3]
[1,]    3    3    3
[2,]    7    7    7
[3,]   11   11   11
                         # quest'ultima operazione si puo' effettuare
                         # con la function crossprod:
t(A)%*%B==crossprod(A,B) # verifica
C<-crossprod(A,B)        #
diag(C)                  # diagonale; funziona anche con matrici non
                         # quadrate:
diag(A)
diag(C) <- c(2,2,2)      # diag() non e' una banale funzione tipo
                         # funzioni fortran o C !!
 
# ATTENZIONE!
> k<-2
> diag(k)
     [,1] [,2]
[1,]    1    0
[2,]    0    1           # a cosa puo' essere utile? venuto per caso?
 
solve(C)                  # matrice inversa
solve(C)%*%C              # verifica      
solve(C)%*%C-C%*%solve(C) # altra verifica (gli zeri sono c.a O(1.e-16))
 
# il motivo del nome 'solve' e' che l'inversione e' usualmente
# un byproduct della soluzione di equazioni lineari
 
b<-c(3,-1,0)     # vettore delle costanti
solve(C,b)       # soluzione del sistema di equazioni lineari
                 # "vettore delle x"
C%*%solve(C,b)   # verifica
 
# matrici simmetriche
# data
S<-matrix(c(1,2,3,2,4,5,3,5,2),3,3)
ev<-eigen(S)     # risolve il problema degli autovalori, 
ev$val           # autovalori   (ev$val sta per ev$values)
ev$vec           # autovettori  (ev$vec sta per ev$vectors)
 
ev$vec[,1]       # autovettore nr 1, etc
                 # check:
S %*% ev$vec[,1] 
ev$values[1] * ev$vec[,1]
                 # attenzione: R distingue fra un'array 3x1 da un
		 # vettore di dimensione 3
 
 
# 5.7.4 singular value decomposition of a generic matrix:
 
s<-svd(C)        # ??? che ci facciamo
 
 
# costruzione di matrici mettendo insieme righe o colonne
# Sec. 5.8
> cbind(c(1,2,3),c(11,22,33),c(101,102,103))
     [,1] [,2] [,3]
[1,]    1   11  101
[2,]    2   22  102
[3,]    3   33  103
> rbind(c(1,2,3),c(11,22,33),c(101,102,103))
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]   11   22   33
[3,]  101  102  103
# in realta', queste funzioni non si aspettano di avere esattemente
# righe intere o colonne intere, ma concatenano tutto quello che viene
# passato
 
# per 'sciogliere' un'array in un vettore
as.vector(z)   # oppure, semplicemente
c(z)