Avatar billede phi-del Nybegynder
09. marts 2006 - 12:18 Der er 31 kommentarer og
2 løsninger

Beregning af stdev.

Hej .

Jeg har følgende variabler med nogle værdier i.
A,B,C,D
og skal finde standardafvigelsen for disse.
er der nogen der kan hjælpe med noget kode i VBA













ps:jeg ved at der findes funktioner som hedder:
DStDev
DStDevP
DVar
DVarP
og man sikkert også bruge dem, men jeg kan ikke finde ud af det..
Avatar billede jensen363 Forsker
09. marts 2006 - 12:21 #1
StdAfv  ???
Avatar billede phi-del Nybegynder
09. marts 2006 - 12:24 #2
det er en slagsmiddelværdi...
Avatar billede phi-del Nybegynder
09. marts 2006 - 12:24 #3
det hedder stdafv i Excel !
Avatar billede jensen363 Forsker
09. marts 2006 - 12:25 #4
Det hedder den også i Access
Avatar billede phi-del Nybegynder
09. marts 2006 - 12:29 #5
hvordan kan jeg bruge den op imod de 4 variabler jeg har ?
hvordan vil koden se ud ?`


sådan ?
test= Stdafv(a,b,c,d)

så melder den sub or function not defined!
Avatar billede terry Ekspert
09. marts 2006 - 12:33 #6
have you looked in help for "Standard deviation"?
Avatar billede terry Ekspert
09. marts 2006 - 12:34 #7
I dont think they can be used accross fields.
Avatar billede phi-del Nybegynder
09. marts 2006 - 12:42 #8
yep men den siger ikke ret meget om det ......
Avatar billede jensen363 Forsker
09. marts 2006 - 13:04 #9
Du skal indarbejde dine data så de står i een tabel/forespørgsen, dvs. vha. UNION
Avatar billede jensen363 Forsker
09. marts 2006 - 13:06 #10
SELECT Tabel.A AS Data
FROM Tabel
UNION
SELECT Tabel.B AS Data
FROM Tabel
UNION
SELECT Tabel.C AS Data
FROM Tabel

osv ....

Derefter laver du StdAfv([Data])
Avatar billede kjulius Novice
09. marts 2006 - 14:08 #11
Iflg. min DB2 manual, så er stddev() = kvadratroden af var() funktionen.


var() er defineret som:

SUM(X**2) / COUNT(X) - (SUM(X) / COUNT(X))**2


Hvis jeg forsøger mig med en omskrivning, så burde du, hvis du har 3 felter (F1, F2 og F3), kunne skrive:


SELECT SQR((F1**2 + F2**2 + F3**2) / 3 - ((F1 + F2 + F3) / 3) ** 2) AS StandarAfvigelse
FROM dintabel


(ikke afprøvet)
Avatar billede jensen363 Forsker
09. marts 2006 - 14:17 #12
Hvad har kvadratroden med standardafvigelse at gøre :o)
Avatar billede kjulius Novice
09. marts 2006 - 14:57 #13
Iflg. manualen er

stdvar() = sqr(var())

altså: standardafvigelsen = kvadratroden af variansen

Jeg kan ikke gennemskue om det er rigtig... :-)
Avatar billede phi-del Nybegynder
09. marts 2006 - 15:20 #14
jamen. venner......
disse værdier A,B,C,D står ikke i en tabel men findes som variabler i
vba..

jeg skal bruge noget kode eks. få det her beregning me disse variabler
Avatar billede phi-del Nybegynder
09. marts 2006 - 15:23 #15
'            Dim sak As Double
'            sak = a * a + b * b + c * c + d * d
'            sums = a + b + c + d
'            i = i - 1
'            stdev = (sak - (sums * sums / i)) / i
'            stdevf = Sqr(stdev)

jeg har det her som melder fejl ved den sidste linie!


og denne fungere hellere ikke :

Kommentar: kjulius
09/03-2006 14:08:19




:(
Avatar billede kjulius Novice
09. marts 2006 - 15:35 #16
Hva' så med denne funktion?

Public Function stdvar(felt1 As Single, Optional felt2 As Single, Optional felt3 As Single, Optional felt4 As Single) As Double
    Dim var As Double
    Dim parametre As Integer
    antalparametre = 1
    sum = felt1
    sum2 = felt1 ^ 2
   
    If Not IsMissing(felt2) Then
        antalparametre = antalparametre + 1
        sum = sum + felt2
        sum2 = sum2 + felt2 ^ 2
    End If
    If Not IsMissing(felt3) Then
        antalparametre = antalparametre + 1
        sum = sum + felt3
        sum2 = sum2 + felt3 ^ 2
    End If
    If Not IsMissing(felt4) Then
        antalparametre = antalparametre + 1
        sum = sum + felt4
        sum2 = sum2 + felt4 ^ 2
    End If
    var = sum2 / antalparametre - (sum / antalparametre) ^ 2
    stdvar = Sqr(var)
End Function
Avatar billede kjulius Novice
09. marts 2006 - 15:49 #17
Jeg havde sløset lidt med dimensioneringen af variablerne (ændrer ikke noget i funktionaliteten), så her er en mere "finpudset" version:

Public Function stdvar(felt1 As Single, Optional felt2 As Single, Optional felt3 As Single, Optional felt4 As Single) As Double
    Dim var As Double
    Dim antalparametre As Integer
    Dim sum As Double
    Dim sum2 As Double
    antalparametre = 1
    sum = felt1
    sum2 = felt1 ^ 2
   
    If Not IsMissing(felt2) Then
        antalparametre = antalparametre + 1
        sum = sum + felt2
        sum2 = sum2 + felt2 ^ 2
    End If
    If Not IsMissing(felt3) Then
        antalparametre = antalparametre + 1
        sum = sum + felt3
        sum2 = sum2 + felt3 ^ 2
    End If
    If Not IsMissing(felt4) Then
        antalparametre = antalparametre + 1
        sum = sum + felt4
        sum2 = sum2 + felt4 ^ 2
    End If
    var = sum2 / antalparametre - (sum / antalparametre) ^ 2
    stdvar = Sqr(var)
End Function
Avatar billede kjulius Novice
09. marts 2006 - 16:14 #18
Oops, den gav forkerte tal. For at den kan afgøre, om en parameter er blevet medsendt, skal variablen være af type variant:

Public Function stdvar(felt1 As Single, Optional felt2 As Variant, Optional felt3 As Variant, Optional felt4 As Variant) As Double
    Dim var As Double
    Dim antalparametre As Integer
    Dim sum As Double
    Dim sum2 As Double
    antalparametre = 1
    sum = felt1
    sum2 = felt1 ^ 2
   
    If Not IsMissing(felt2) Then
        antalparametre = antalparametre + 1
        sum = sum + felt2
        sum2 = sum2 + felt2 ^ 2
    End If
    If Not IsMissing(felt3) Then
        antalparametre = antalparametre + 1
        sum = sum + felt3
        sum2 = sum2 + felt3 ^ 2
    End If
    If Not IsMissing(felt4) Then
        antalparametre = antalparametre + 1
        sum = sum + felt4
        sum2 = sum2 + felt4 ^ 2
    End If
    var = sum2 / antalparametre - (sum / antalparametre) ^ 2
    stdvar = Sqr(var)
End Function
Avatar billede kjulius Novice
09. marts 2006 - 16:17 #19
Test:

?stdvar(3.5, 3.5, 3.5)
0

?stdvar(3.5, 3.5, 8.5)
2,35702260395516

?stdvar(3.5, 3.5, 8.5, 4.33)
2,07314224065789
Avatar billede kjulius Novice
09. marts 2006 - 16:23 #20
Funktionen burde vel have heddet stddev, men det kan du selv ændre... :-)
Avatar billede arne_v Ekspert
09. marts 2006 - 20:36 #21
den brugte formel er korrekt

og den bruges nogle gange fordi man kan noejes med at gennemloebe data en gang

andre gange fravaelges den fordi den kan give numeriske problemer

hvis man foretraekker "text book" formlerne saa

Function Mean(A As Double, B As Double, C As Double, D As Double) As Double
    Mean = (A + B + C + D) / 4
End Function

Function Var(A As Double, B As Double, C As Double, D As Double) As Double
    Dim m As Double
    m = Mean(A, B, C, D)
    Var = ((A - m) ^ 2 + (B - m) ^ 2 + (C - m) ^ 2 + (D - m) ^ 2) / 4
End Function

Function StdDev(A As Double, B As Double, C As Double, D As Double) As Double
    StdDev = Sqr(Var(A, B, C, D))
End Function
Avatar billede kjulius Novice
09. marts 2006 - 22:52 #22
Hvor stor er forskellen i præcision mellem de to formler (den som bl.a. DB2 bruger i sin databasemotor) og så din studiebogsudgave (som jeg går ud fra er mere korrekt?).

Det er forhåbentlig ikke særligt meget resultaterne fra de to beregningsformer afviger fra hinanden? Jeg vil da gerne kunne stole på den udregning DB2 bruger.
Avatar billede arne_v Ekspert
09. marts 2006 - 23:08 #23
formlerne er matematisk 100% ekvivalente

du kan simpelthen omskrive den ene til den anden

den slags kunne jeg udenad for godt 20 aar siden

det er et problem som giver sig udslag paa computere p.g.a. den begraensede
praecision af float og double

grundliggende samme problem der goer at det er strengt forbudt at bruge
float og double til penge i databaser

jeg kan godt proeve at lave et eksempel
Avatar billede arne_v Ekspert
09. marts 2006 - 23:29 #24
Option Compare Database

Function Mean(A As Double, B As Double, C As Double, D As Double) As Double
    Mean = (A + B + C + D) / 4
End Function

Function Var(A As Double, B As Double, C As Double, D As Double) As Double
    Dim m As Double
    m = Mean(A, B, C, D)
    Var = ((A - m) ^ 2 + (B - m) ^ 2 + (C - m) ^ 2 + (D - m) ^ 2) / 4
End Function

Function StdDev(A As Double, B As Double, C As Double, D As Double) As Double
    StdDev = Sqr(Var(A, B, C, D))
End Function

Function FastVar(A As Double, B As Double, C As Double, D As Double) As Double
    FastVar = (A ^ 2 + B ^ 2 + C ^ 2 + D ^ 2) / 4 - ((A + B + C + D) / 4) ^ 2
End Function

Function FastStdDev(A As Double, B As Double, C As Double, D As Double) As Double
    FastStdDev = Sqr(FastVar(A, B, C, D))
End Function

Function Test()
    MsgBox CStr(StdDev(0, 1, 2, 3))
    MsgBox CStr(FastStdDev(0, 1, 2, 3))
    MsgBox CStr(StdDev(10000000000000#, 10000000000001#, 10000000000002#, 10000000000003#))
    MsgBox CStr(FastStdDev(10000000000000#, 10000000000001#, 10000000000002#, 10000000000003#))
End Function
Avatar billede phi-del Nybegynder
10. marts 2006 - 10:23 #25
Det er jo smart med alle de forskellige funktioner, men hvad nu hvis det istedet for 4 er 3 variabler ?
Avatar billede phi-del Nybegynder
10. marts 2006 - 10:26 #26
ok nu prøver jeg det her

  m = Mean(A, B, C, D, E)

også melder den
Compile error:

Byref argument type mismatch

functionen ser sådan ud :
Function Mean(A As Double, B As Double, C As Double, D As Double, N As Double)
    Mean = (A + B + C + D) / 4
End Function
Avatar billede arne_v Ekspert
10. marts 2006 - 13:28 #27
Normalt sender man et array over til den slags funktioner - jeg fortsatte bare
med argumenter fordi det havde I - jeg undlod dog at lave argumenterne optionelle
Avatar billede kjulius Novice
10. marts 2006 - 18:47 #28
---> phi-del:

Fejlmeldingen betyder, at de variabler (A, B, C, ...) du kalder rutinen med ikke er defineret som double. Som standard overfører VB(A) ikke værdier, men derimod en pointer til den variabel du bruger.

Derfor, hvis du ønsker en rutine, som skal kunne kaldes fra mange forskellige steder i et program og med flere variabeltyper (integer, single, double osv.), så er det en god ide at gøre et af to ting:

1. definere parametrene med variabeltypen Variant, som er en speciel type som kan indeholde alle de andre typer. Så skal du bare teste for typen i rutinen.
2. definere parametrene med en Byval, sådan at det er værdierne der bliver overført, og ikke pointeren til de oprindelige variable.

Hvis du ønsker at gøre en parameter optional (dansk: valgfri), skal du bruge variabeltypen Variant.
Se evt. mit bidrag fra 09/03-2006 16:14:29
Avatar billede kjulius Novice
20. marts 2006 - 00:40 #29
---> phi-del: Har du fundet ud af det?

Som arne_v fortalte, så er den bedste metode til at overdrage parametrene, hvis du bruger en array. VBA understøtter dette gennem ParamArray.

Den rutine jeg viste i mit indlæg fra 09/03-2006 16:14:29 ville med denne metode se sådan ud:

Public Function Stddev(ByVal Param1 As Double, ParamArray f()) As Double
    ' Den hurtige udgave med kun et gennemløb...
    Dim p As Long, x As Long, al As Long, au As Long
    Dim s As Double, s2 As Double, Avg As Double, Var As Double
    If Not IsMissing(f()) Then
        al = LBound(f()): au = UBound(f()): p = au - al + 2
        s = Param1
        s2 = Param1 ^ 2
        For x = al To au
            If IsNumeric(f(x)) Then
                s = s + f(x)
                s2 = s2 + f(x) ^ 2
            Else
                MsgBox "Kun numeriske værdier er acceptable.", _
                    vbExclamation + vbApplicationModal + vbOKOnly, _
                    "Fejl i funktionsparametre"
                Exit Function
            End If
        Next
        Avg = s / p
        Var = s2 / p - (s / p) ^ 2
        Stddev = Sqr(Var)
    Else
        Avg = Param1
        Var = 0
        Stddev = 0
    End If
End Function

Men som arne_v korrekt påpegede, så giver denne udregning forkerte resultater ved store værdier p.g.a afrundingsfejl (selv Double variabler er ikke præcise nok), så med hans korrektioner, er en mere præcis rutine:

Public Function Stddev(ByVal Param1 As Double, ParamArray f()) As Double
    ' Den mere korrekte version...
    Dim p As Long, x As Long, al As Long, au As Long
    Dim s As Double, s2 As Double, Avg As Double, Var As Double
    If Not IsMissing(f()) Then
        al = LBound(f()): au = UBound(f()): p = au - al + 2
        s = Param1
        For x = al To au
            If IsNumeric(f(x)) Then
                s = s + f(x)
            Else
                MsgBox "Kun numeriske værdier er acceptable.", _
                    vbExclamation + vbApplicationModal + vbOKOnly, _
                    "Fejl i funktionsparametre"
                Exit Function
            End If
        Next
        Avg = s / p
        s2 = (Param1 - Avg) ^ 2
        For x = al To au
            s2 = s2 + (f(x) - Avg) ^ 2
        Next
        Var = s2 / p
        Stddev = Sqr(Var)
    Else
        Avg = Param1
        Var = 0
        Stddev = 0
    End If
End Function

Begge funktioner er fleksible, så man kan angive så mange eller så få parametre man har brug for.
Avatar billede phi-del Nybegynder
05. april 2006 - 12:25 #30
det er nok tid til at lukke dette emne, mener at have fået løst det, men alle forslag har været tilhjælp.
kunne i ikke indlægge et svar ?
Avatar billede kjulius Novice
05. april 2006 - 18:18 #31
Sure, no problem...
Avatar billede arne_v Ekspert
05. april 2006 - 18:38 #32
.
Avatar billede phi-del Nybegynder
18. april 2006 - 08:46 #33
Takker for hjælpen :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester