Condividi:        

Contare numeri presenti in una matrice

Vuoi potenziare i tuoi documenti Word? Non sai come si fa una macro in Excel? Devi creare una presentazione in PowerPoint?
Oppure sei passato a OpenOffice e non sei sicuro di come lavorare al meglio?

Moderatori: Anthony47, Flash30005

Contare numeri presenti in una matrice

Postdi Francesco53 » 18/05/12 16:59

Buonaserata a tutto il Forum, stò cercando di capire qualcosa su Variabili e matrici.
1) Domanda si può assegnare alla variabile un valore determinato da una elaborazione?
faccio esempio:
UR = Worksheets("Archivio").Range("B" & Rows.Count).End(xlUp).Row - 1
Dim EN(UR, 5)

Prendendo spunto da un Archivio di dati, ho fatto fare una ricerca di numeri in una determinata
circostanza, esempio prima lettura di ogni mese, e memorizzo i dati nella variabile.
Con i seguenti comandi riesco a scrivere al fianco di ogni lettura i parametri rilevati:
For T = 2 To UR
For COL = 1 To 5
Cells(T, 25 + COL) = EN(T, COL)
Next
Next
2) Domanda: se i valori presenti nella matrice, li volessi contare? come fare?
Esempio i valori possono andare da 1 a 50, per cui anzichè scrivere i valori,
vorrei scrivere direttamente il numero di presenze del dato, per cui farei:
Dim US(50, 1)
For L = 1 to UR 'numero totale letture
For M = 1 to 5 'numero dati letti da 1 a 5
For I = 1 to 50 'possibili valori del dato da 1 a 50
If EX(L,M) = I Then
Conta = Conta + 1
US(I, Conta)
Next
Next
Next
Dovrei aver scritto delle stupidaggini, ma spero di essere riuscito a far capire cosa vorrei ottenere.
Avere direttamente i totali delle letture di ogni numero da 1 a 50.
Grazie a chi può aiutarmi a capire.
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Sponsor
 

Re: Contare numeri presenti in una matrice

Postdi Zer0Kelvin » 18/05/12 17:27

Ciao.
In effetti a me non è chiaro quello che vuoi ottenere, ma ho il sospetto che si possa fare senza ricorrere a VBA, a meno che non vi siano altre esigenze di elaborazione che non hai citato.
Dal lato "foglio" ci sono funzioni come CONTA.SE e CONTA.VALORI che permettono di fare quello che dici, probabilmente.
Magari potresti postare un esempio con una descrizione del risultato che vorresti ottenere.
[Win7,Office2010]
Condividere la conoscenza aumenta la ricchezza di tutti(Z0°K)
Dai ad un uomo un pesce e lo avrai sfamato per un giorno;insegnagli a pescare e lo avrai sfamato per sempre(Confucio)
Il sonno della ragione genera mostri(Francisco Goya)
Avatar utente
Zer0Kelvin
Utente Senior
 
Post: 388
Iscritto il: 08/04/12 11:23

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 18/05/12 17:48

Ciao Zer0Kelvin, sò che si può fare con formule e con semplice codice vba,
ma a me serve capire come lavorare con la memorizzazione dei dati in una variabile,
quindi come chiedevo, contare le presenze memorizzate all'interno di esse per singolo dato.
Vorrei provare a lavorare solo con la memoria per sveltire degli aspetti che mi interessano.
Grazie
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi patel » 18/05/12 18:30

Anche io non ho capito l'obiettivo e nemmeno il titolo, la matrice la crei tu quindi tu sai cosa ci hai messo.
patel
Utente Senior
 
Post: 309
Iscritto il: 24/04/12 16:03

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 18/05/12 20:34

Cerco di chiarire:
Una volta memorizzati i dati in EN(UR, 5) esempio
1,1 = 3; 1,2 = 6; 1,3 = 7; 1,4 = 5; 1,5 = 12
2,1 = 4; 2,2 = 12; 2,3 = 8; 2,4 = 22; 2,5 = 6
3,1 = 6; 3,2 = 12; 3,3 = 15; 3,4 = 3; 3,5 = 1
Avremo la seguente situazione
Valore 1 presente 1
Valore 2 presente 0
Valore 3 presente 2
Valore 4 presente 1
...........................
Valore 6 presente 2
Valore 12 presente 3
etc.etc.etc.
Ora io ho la necessita' di memorizzare in Dim US(50, 1)
dove esempio:
US(1,1) perchè il num 1 è presente 1 volta,
US(2,1) perchè il num 2 è presente 0 volte,
...........................................
US(6,1) perchè il num 6 è presente 2 volte,
US(12,1) perchè il num 12 è presente 3 volte.
Ora ho la necessità con un ciclo for .. next
di scrivere tutti i valori relativi alle presenze dei 50 numeri.
For Z = 1 to 50
Cells(Z,20) = US(Z,1)
Next
Si può fare?
Grazie
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Zer0Kelvin » 18/05/12 21:00

Ciao... e bravo per aver smesso di fumare.
Io invece ...
Comunque il codice dovrebbe essere questo:
Codice: Seleziona tutto
Option Base 1

Private Sub conta()
Dim US(50) As Byte, iUS As Long, L As Long, M As Long
    '......
    '......
    For iUS = 1 To 50
        For L = 1 To UR 'numero totale letture
            For M = 1 To 5 'numero dati letti da 1 a 5
                If EN(L, M) = iUS Then US(iUS) = US(iUS) + 1
            Next M
        Next L
    Next iUS
End Sub

alla fine dovresti ottenere
-in US(1) il n° di valori 1 rilevati
-in US(2) il n° di valori 2 rilevati
e cosi via...
Non l'ho testata, ma se ho capito bene dovrebbe funzionare.
[Win7,Office2010]
Condividere la conoscenza aumenta la ricchezza di tutti(Z0°K)
Dai ad un uomo un pesce e lo avrai sfamato per un giorno;insegnagli a pescare e lo avrai sfamato per sempre(Confucio)
Il sonno della ragione genera mostri(Francisco Goya)
Avatar utente
Zer0Kelvin
Utente Senior
 
Post: 388
Iscritto il: 08/04/12 11:23

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 18/05/12 22:22

Grazie Zer0Kelvin,
è perfetto.
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Anthony47 » 18/05/12 23:16

Aggiungo qualche informazione che potrebbe essere utile:
-se dichiari una variabile di tipo variant (basta Dim MiaVar) essa potra' contenere anche una matrice. Ad esempio
Codice: Seleziona tutto
MiaVAr = Range("A1:E50").Value
ti mettera' in MiaVAr una matrice di 50*5

Analogamente potrai caricare un range direttamente con questa matrice usando ad esempio
Codice: Seleziona tutto
Range("K1:K50") = MiaVAr


Quando la variant contiene una matrice puoi accedere alle singole informazioni come si fa con le matrici, es
Codice: Seleziona tutto
pippo = MiaVAr(10, 1)


Per evitare di usare indici non inclusi negli intervalli puoi leggere quali sono i limiti inferiori e suoperiori con LBound e UBound; es con questa imposti un ciclo dalla prima all' ultima riga della matrice
Codice: Seleziona tutto
For I=LBound(MiaVar,1) to UBound(MiaVar,1)


IN ALTERNATIVA puoi definire una vera matrice ma in questo caso non riuscirai a fare un "bulk loading" (un range in tutta la matrice) ma dovrai caricare elemento per elemento.

Se vuoi poter ridimensionare una marice allora definiscila come matrice ma senza dimensioni, e poi potrai usare l' istruzione Redim per assegnare o variare le dimensioni; es
Codice: Seleziona tutto
Dim MiaMatr()
'..
'..
Redim MiaMatr(UR,5)      'UR deve contenere un numero

Redim consente anche di "mantenere" il contenuto esistente mentre si varia "l' ultima" sua dimensione; vedi l' help on line di Redim per la sintassi, e soprattutto fai qualche prova.

Scrivo queste cose perche' mi e' sembrato nel primo post che ci fosse un interesse per il tema.

Ciao a tutti.
Avatar utente
Anthony47
Moderatore
 
Post: 19196
Iscritto il: 21/03/06 16:03
Località: Ivrea

Re: Contare numeri presenti in una matrice

Postdi Flash30005 » 19/05/12 01:20

Ottima la spiegazione sulle matrici di Anthony: faccio tesoro! ;)

Per quanto riguarda il quesito, suppongo che Francesco53: "vecchio volpone" di analisi di archivi, abbia bisogno di "memorizzare" in Vettori il conteggio dei numeri usciti dalle estrazioni per utilizzarli successivamente nella stessa macro e quindi voglia adottare questo sistema.
Sapete bene quanto prediligo le macro rispetto alle formule, specialmente se le formule sono centinaia o migliaia.
In questo caso, però con sole 50 formule si ha in una colonna prestabilita e in tempo reale, il risultato voluto.
Ammettendo che l'archivio sia da A1 a Ex
Si potrebbe pensare di
1) usare la colonna "I" da I1 a I50 per inserire i 50 numeri (colonna eliminabile ma utile per riconoscere i numeri interessati)
2) definire un elenco dinamico con inserisci nome da "Inserisci", definisci (nome) "Archivio"
Codice: Seleziona tutto
=INDIRETTO("A1:E"&CONTA.VALORI(Foglio1!$A:$A))

3) inserire in "J1" questa formula
Codice: Seleziona tutto
=SE(CONTA.SE(Archivio;I1)=0;"";CONTA.SE(Archivio;I1))

e trascinarla fino a J50 per avere il conteggio di ogni numero (di colonna "I") nell'archivio "A1:Ex"
La colonna J (da 1 a 50) è disponibile per ogni conteggio o calcolo successivo.

Se non occorre il riferimento numerico (di 1 a 50) allora la formula in J1....
potrebbe prendere il riferimento riga
Codice: Seleziona tutto
=SE(CONTA.SE(Archivio;RIF.RIGA())=0;"";CONTA.SE(Archivio;RIF.RIGA()))

eliminando così i valori in colonna "I"

Questo metodo è stato usato anche nel programma "FreqAmbiTerni10ELotto...xls" che hai scaricato ;)

Ciao
Flash
Win10 + Office 2010 Ita
"Fotografica" al servizio dell'immagine
Avatar utente
Flash30005
Moderatore
 
Post: 8517
Iscritto il: 27/09/07 11:44
Località: Roma +o-

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 19/05/12 08:34

Ringrazio Anthony per le spiegazioni, le ho copiate e le studierò per migliorare le mie conoscenze.
Ringrazio Flash per i suoi spunti e suggerimenti. Stò cercando di realizzare delle analisi su archivio
che, a differenza del mio solito modo di operare, molte formule, copie dati e poi analisi, faccia tutte le
analisi tramite variabili e analisi matrici per utilizzare esclusivamente la memoria e rendere più veloce
il tutto. Spero sia così! dovrebbe essere così! non lo sò, ci provo. :)
Grazie
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Anthony47 » 19/05/12 13:42

IN ALTERNATIVA puoi definire una vera matrice ma in questo caso non riuscirai a fare un "bulk loading" (un range in tutta la matrice) ma dovrai caricare elemento per elemento.

Mi e' stato fatto notare che questa mia afferrmazione e' sbagliata; infatti e' sufficiente dichiarare la matrice senza dimensioni per poi poterci caricare il contenuto di un intervallo; esempio
Codice: Seleziona tutto
Dim Matrice()
'..
'..
Matrice = Range("A2:Z151")


Le operazioni eseguite in memoria sono piu' veloci di quelle eseguite sulle celle, anche se l' impatto finale dipende anche dagli algoritmi di lavoro adottati.

Ciao
Avatar utente
Anthony47
Moderatore
 
Post: 19196
Iscritto il: 21/03/06 16:03
Località: Ivrea

Re: Contare numeri presenti in una matrice

Postdi patel » 19/05/12 13:54

aggiungo che è meglio anteporre al codice la dichiarazione
Codice: Seleziona tutto
option base 1
altrimenti si possono avere sorprese con l'istruzione
Codice: Seleziona tutto
Range("K1:K50") = MiaVAr
patel
Utente Senior
 
Post: 309
Iscritto il: 24/04/12 16:03

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 19/05/12 14:10

Ciao patel, avevo bisogno di capire con
option base 1
cosa intendi?
generalmente leggevo Option Explicit
che intendeva, se non sbaglio, la dichiarazine di tutte le variabili.
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Zer0Kelvin » 19/05/12 14:46

Se osservi la macro che ho postato noterai
Codice: Seleziona tutto
Option Base 1

Private Sub conta()
Dim US(50) As Byte...

In VB il primo indice di una matrice è 0 quindi se io dichiaro
US(50)
il primo elemento della matrice sarà
US(0)
e l'ultimo
US(49)
L'istruzione Option Base 1 dice a Visual Basic di usare 1 come primo indice, così si evitano sorprese quando si và a scorrere la matrice.
Se per esempio io avessi omesso Option Base 1, il ciclo
Codice: Seleziona tutto
    For iUS = 1 To 50
        ...
                If EN(L, M) = iUS Then US(iUS) = US(iUS) + 1

avrebbe generato un errore per iUS=50, in quanto l'ultimo elemento della matrice sarebbe stato:
US(49)
:cry:
[Win7,Office2010]
Condividere la conoscenza aumenta la ricchezza di tutti(Z0°K)
Dai ad un uomo un pesce e lo avrai sfamato per un giorno;insegnagli a pescare e lo avrai sfamato per sempre(Confucio)
Il sonno della ragione genera mostri(Francisco Goya)
Avatar utente
Zer0Kelvin
Utente Senior
 
Post: 388
Iscritto il: 08/04/12 11:23

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 19/05/12 16:37

Grazie Zer0Kelvin, sei stato chiaro nella risposta.
Come tutti sapete, l'appetito vien mangiando e quando si tratta di sapere, spesso è anche più forte la necessità.
Avrei da porre un'ulteriore domanda, con la seguente macro postata da Zer0Kelvin, potevo scrivere i dati rilevati:
Codice: Seleziona tutto
    Option Base 1

    Private Sub conta()
    Dim US(50) As Byte, iUS As Long, L As Long, M As Long
        '......
        '......
        For iUS = 1 To 50
            For L = 1 To UR 'numero totale letture
                For M = 1 To 5 'numero dati letti da 1 a 5
                    If EN(L, M) = iUS Then US(iUS) = US(iUS) + 1
                Next M
            Next L
        Cells ( 1, 30 + iUS) = US(iUS)     '>>>> qui scrivevo i dati in ordine dal 1 al 50mo
        Next iUS
    End Sub


DOMANDA:
Se io volessi stampare solo i primi 10 numeri con più presenze e non tutti i 50, esiste un comando per ordinare la matrice?
e di conseguenza utilizzare solo i primi 10 numeri che hanno una maggiore presenza?
Spero di non domandare troppo, un grazie comunque a tutti voi per la disponibilità.
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 19/05/12 16:47

Scusate per chiarire meglio la richiesta fatta sopra,
come già avevo scritto:
1,1 = 3; 1,2 = 6; 1,3 = 7; 1,4 = 5; 1,5 = 12
2,1 = 4; 2,2 = 12; 2,3 = 8; 2,4 = 22; 2,5 = 6
3,1 = 6; 3,2 = 12; 3,3 = 15; 3,4 = 3; 3,5 = 1
Avremo la seguente situazione
Valore 1 presente 1
Valore 2 presente 0
Valore 3 presente 2
Valore 4 presente 1
...........................
Valore 6 presente 2
Valore 12 presente 3
dovrei aver la seguente il seguente risultato:
N 12 - 6 - 3 - 4 - 1 - 2
Pr 3 - 2 - 2 - 1 - 1 - 0
per quello io pensavo necessitasse una matrice bidimensionale (N,Pr).
Grazie
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45

Re: Contare numeri presenti in una matrice

Postdi Anthony47 » 20/05/12 01:50

Option base colpisce ancora...
aggiungo che è meglio anteporre al codice la dichiarazione
option base 1

altrimenti si possono avere sorprese con l'istruzione
Range("K1:K50") = MiaVAr

Mi permetto di dire che l' uso di Option Base 1 e' piu' che altro legato al proprio stile di programmazione; in ogni caso non ha impatto in istruzioni quali Range("K1:K50") = MiaVAr che popola K1:K50 attingendo dalla prima colonna di MiaVAr; ne' ha impatto sull' istruzione opposta, es MiaVAr=Range("A1:C100") che mette nella variant MiaVArr (che deve essere stata dichiarata come variant) una tabella di 100 righe*3 colonne.
Inoltre in questi casi la matrice viene creata sempre con base=1, anche se tra le dichiarazioni ci fosse Option Base 0

In VB il primo indice di una matrice è 0 quindi se io dichiaro
US(50) il primo elemento della matrice sarà US(0) e l'ultimo US(49)

In realta' con US(50) si definisce una matrice con l' indice piu' alto pari a 50; quindi la matrice avra' 50 posizioni se Option Base 1, oppure 51 se Option Base 0 (valore di default)

Una ragione in piu' per usare "spesso" le funzioni UBound (indice superiore) e LBound (indice inferiore) per calcolare gli indici della matrice.

Andando alla richiesta di elencare solo i 10 numeri piu' presenti, prova qualcosa come:
Codice: Seleziona tutto
Sub Top10()
'
Dim MiaVAr, mioCount(1 To 90), MiaTop(1 To 10, 1 To 2)
[P1] = Timer
MiaVAr = Range("A1:E50").Value
'scan matrice in memoria e calcolo presenze
For xI = 1 To 50
    For yI = 1 To 5
        If MiaVAr(xI, yI) <> "" Then mioCount(MiaVAr(xI, yI)) = mioCount(MiaVAr(xI, yI)) + 1
    Next yI
Next xI
'Cerca i top 10
For I = 1 To 10
    topC = Application.WorksheetFunction.Large(mioCount(), 1)   'top Counter
    topN = Application.Match(topC, mioCount(), 0)               'top Number
    MiaTop(I, 1) = topN  '*1
    MiaTop(I, 2) = topC  '*1
'Cells(I, 9) = topN  '*2
'Cells(I, 10) = topC  '*2
    mioCount(topN) = 0
Next I
'report in I1:J10
Range("I1:J10") = MiaTop  '*1
[p2] = Timer
End Sub
Tuttavia in questo caso il vantaggio di portare in matrice la tabella iniziale (che ho immaginato essere in A1:E50) e' minimo, perche' usando la matrice siamo poi costretti a scansionare tutte le sue celle per contare le presenze, mentre lavorando con i dati del foglio e' possibile usare la WorksheetFunction.CountIf per calcolare direttamente lo stesso dato; diciamo che nel caso matrice i tempi sono 3-4 msec e nel caso dati su foglio sono 4-5 msec.
La macro descritta usa tre matrici:
- MiaVAr per copiarci i dati dal foglio
-mioCount(1 To 90), in cui calcolo il numero delle presenze per ogni numero (ho immaginato che i numeri siano 90)
-MiaTop(1 To 10, 1 To 2), in cui accumulo i top 10 che poi vengono scaricati nell' area I1:J10. Notate che avrei potuto scrivere i risultati direttamente nelle celle I1:J10, eliminando le tre istruzioni marcate *1 e abilitando le due marcate *2; in questo caso pero' i tempi di esecuzione cambiano da 3-4 msec a 15-20 msec: pochi millisecondi, che danno pero' l' idea di quanto sia oneroso scrivere nelle celle.

Ciao a tutti.
Avatar utente
Anthony47
Moderatore
 
Post: 19196
Iscritto il: 21/03/06 16:03
Località: Ivrea

Re: Contare numeri presenti in una matrice

Postdi Francesco53 » 20/05/12 09:54

Buongiorno a tutti, e nuovamente grazie per la vostra disponibilità.
X Anthony, studierò con attenzione e cercherò di utilizzare e capire la macro da te postata, grazie.
Volevo intervenire per quanto concerne i tempi di esecuzione:
Il lavoro che mi stò divertendo a realizzare, utilizzando le classiche macro, scrivendo nelle celle i risultati, calcolando
conteggi e ordinando i dati, per una ventina di cicli, impiega poco più di 3 minuti. Utilizzando le variabili e le matrici
i tempi si riducono a 10 sec., pur scrivendo in 180 celle i risultati.
Ora, io spero di capire quest'ultima macro postata per continuare a lavorare solo con la memoria e quindi, contenere
i tempi di elaborazione al minimo indispensabile.
Ma sopratutto imparare a gestire tramite variabili e matrici i dati da elaborare.
Grazie a presto.
Francesco
S.O. Windows 10 e Office 2007
Avatar utente
Francesco53
Utente Senior
 
Post: 811
Iscritto il: 20/02/10 18:45


Torna a Applicazioni Office Windows


Topic correlati a "Contare numeri presenti in una matrice":


Chi c’è in linea

Visitano il forum: Nessuno e 53 ospiti