Home Engidea Home Circle

Come trasformare un insieme di misure in una curva gaussiana

Supponiamo che abbiate un insieme di misure, ad esempio di lunghezza, e vogliate vedere quale sia la distribuzione di queste misure, cioè volete dividere l'intervallo dei valori in un numero di parti uguali, contare quanti valori cadano in quell'intervallo e quindi costruire un grafico che rappresenti la distribuzione dei valori nell'intervallo.

La mia soluzione usa OpenOffice e in particolare Calc ed è una macro che prende dei dati, trova il minimo e massimo e dato il numero di intervalli desiderati determina il delta per ogni intervallo. Dopodichè per ogni intervallo calcola il numero di misure al suo interno e mette il risultato nella tabella.

La macro è interessante per l'uso che si fa dei riferimenti(nomi), e degli array.

I nomi sono un modo elegante per evitare di usare dei riferimenti assoluti all'interno delle vostre macro. Si accede alla definizione dei nomi attraverso il seguente menu.

Ad esempio ho definito una serie di nomi che si riferiscono a parti del foglio in modo da poterli usare nella macro

La struttura della macro è abbastanza semplice
per prima cosa si ripescano i valori che interessano, successivamente vi è un semplice loop che inserisce i valori in una colonna ed una funzione che calcola il numero di valori nell'intervallo.

Option Explicit

Sub GaussMake

Dim Document As Object
Document = ThisComponent

Dim allSheets As Object
allSheets = Document.getSheets()

' this is used to have access to CALC embedded functions
Dim svc As Object
svc = createUnoService( "com.sun.star.sheet.FunctionAccess" )

Dim currentSheet As Object
currentSheet = ThisComponent.CurrentController.ActiveSheet


'to have access to the following labels you MUST define them using
' Insert->names->Define
' and give the correct names to the single cells or range

Dim minLen As Double
minLen = currentSheet.getCellRangeByName("min_len").getValue()

Dim maxLen As Double
maxLen = currentSheet.getCellRangeByName("max_len").getValue()

Dim stepsNum As Integer
stepsNum = currentSheet.getCellRangeByName("steps_num").getValue()

Dim delta As Double
delta = currentSheet.getCellRangeByName("delta").getValue()

'msgBox("stepsNum="+stepsNum)

'Xray currentSheet.getCellRangeByName("raw_data")

Dim srcCell as Object
Dim destCell as Object

'cell numbering starts at 0, meaning tat A1 is 0,0
'	srcCell = sourceSheet.getCellRangeByPosition(2,rowIndex)

Dim intervals As integer
Dim rowIndex as integer
Dim destRow As integer

Const indexCol = 7
Const minCol = 8
Const maxCol = 9
Const countCol = 10

Dim curMin  As Double
curMin = minLen

Dim curMax As Double
Dim counted As Integer

For intervals = 1 to stepsNum

	' I need to know where to put the correct answer
	destRow = intervals+8   ' since counting starts at zero but it is visually represented as 1
	destCell = currentSheet.getCellByPosition(indexCol,destRow)
	destCell.setValue(intervals)

	destCell = currentSheet.getCellByPosition(minCol,destRow)
	destCell.setValue(curMin)

	destCell = currentSheet.getCellByPosition(minCol,destRow)
	destCell.setValue(curMin)

	curMax = curMin + delta

	destCell = currentSheet.getCellByPosition(maxCol,destRow)
	destCell.setValue(curMax)

	' here I do some counting
    counted = countRange (currentSheet.getCellRangeByName("raw_data"), curMin, curMax )
	destCell = currentSheet.getCellByPosition(countCol,destRow)
	destCell.setValue(counted)

	' then update min
	curMin = curMax


'	randPos = svc.callFunction( "RAND", arg )

Next


'srcCell = destSheet.getCellRangeByName("B2")
'ThisComponent.CurrentController.select(srcCell)

'msgBox ( "prova"+svc.callFunction( "RAND", arg ) )

' Look for Xray and OpenOffice to find out what it does, basically it is a powerful
' tool to understand properties and methods of objects.
'Xray destCell

End Sub

' search in the given range the number of elements that are within min and max

Function countRange ( range As variant, min As Double, max As double ) As Integer

    'un array si definisce così
	Dim rawData() As Object
	rawData = range.getData()

	Dim index As integer
	Dim risul As Integer
	DIm subarray() as Object
	Dim value as Double

	For index = LBound(rawData()) To UBound(rawData())
        'apparentemente  i dati sono contenuti in un sottoarray di un elemento
		subarray = rawData(index)
		value = subarray(0)

		if ( value >= min AND value > max ) then risul = risul + 1
	Next

'Xray rawData

	countRange() = risul

End Function

Per evitarvi di digitare la macro vi allego il file Calc in modo che possiate provare le cose in maniera semplice.

I commenti sono benvenuti

Se trovate questo articolo utile potete lasciarmi un messaggio semplicemente scrivendolo qui sotto e spedendolo con il tasto lettera.

   

Last update 07/02/2007