Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
840to844
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
840to844
840to844
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

Stichprobenziehung mit VBA

Stichprobenziehung mit VBA
30.01.2007 14:16:35
Marcus
Hallo,
ich möchte gerne in MS-Excel aus einer Datenmatrix eine Stichprobe mit Hilfe von VBA ziehen. Hierbei sollen bestimmte Grundvoraussetzungen berücksichtigt werden:
1. Insgesamt sollen Einträge mit einer bestimmten Kennung (eines bestimmten Typs) 50 Prozent der Gesamtstichprobe ausmachen.
2. Es soll gewährleistet sein, dass mindestens 50 Prozent aller möglichen Kennungen (Typen) berücksichtigt werden.
3. Es sollen je Zeile in der Datenmatrix nur maximal 3 Stichproben gezogen werden.
Simultan oder anschließend sollen die Daten der gezogenen Stichprobe (die jeweiligen Zellinhalte) in eine andere Tabelle übertragen werden.
Eine Beispielmatrix mit den Kriterien habe ich beigelegt (https://www.herber.de/bbs/user/40008.xls).
Über Hilfe würde ich mich sehr freuen,
Marcus

5
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Stichprobenziehung mit VBA
30.01.2007 19:22:35
ingUR
Hallo, Markus,
wazu Du hier Hilfe erbittest, das sind keine direkten EXCE/VBA-Fragen sondern das ist ein Projekt.
Während der dritte Punkt Deines Dedingungskatalogs recht einfach umgesetzt werden kann (Indexfeld, das für jedes Element eines Datensatz, den Datenzähler um eins erhöht, bis dieser den Wert 3 hat), fehlen mir zu den beiden anderen Punkten der Überblick über die möglichen Besonderheiten zur Struktur der Daten.
Handelt es sich hier um eine Zeitreihe für die die Information zeiliche Reihenfolge nicht verloren gehen darf? Sind immer alle Einträge eines Datensatzes gefüllt?
Wenn die Kennung X als "Leitkennung" mindestens 50% der genommen Stichproben ausmachen soll, dann gilt es zuerst die Häufigkeit in den Klassen (Typ A1, B1,...) zu bestimmen um so festzustellen, wie groß die Anzahl der Elemente der Stichprobe maximal werden kann.
Da 50% dieser Menge für den "Leittyp" u reservieren sind, verbleibenden die übrigen 50% für die übrigen Stichproben aus den Werten der Mende der Typen ohne Leittyp. Diese wiederung gliedern sich so, dass jeweils 50% eines jeden "Sekundärtyps" im Stichprobenumfang auftauchen sollen:
Dein Beispiel:
Es esistieren von A1 (Leittyp) 11 Elemente in dem Gesmtumfang der Daten. Die Bedingung, dass dieser Typ 50% im Stichprobenumfang ausmacht, ergibt die Anzahl des Stichprobenumfangs, nämlich 2*(11*0,5) = 12 (ganzahlig auf die nächsthöhere, durch 2 teilbare Zahl aufgerundet).
Nun ist sicher zustellen, dass die Summe von jeweils 50% der Anzahl eines jeden weiteren Types mindestens die restlichen 50% des Stichprobenumfanges füllen können.
In Deinem Beispiel: 50%*(B1:3 + B2:4 + C1:3 + C2:4)= 7 > 12/6. Damit wäre hier eine zusätzlich Bedingung Deiner Stichprobenauswahl möglich, wenn auch das Kriterium der Begrenzung auf drei Elemente je Datensatz beachtet werden kann.
Das allerdings birgt nach meinem derzeitigen Überlegungen die Gefahr, dass die Aufgabe nur eingeschränkt erfüllt werden kann; z.B. es wird noch ein Element C1 benötigt, kann aber nicht gesetzt werden, da sich alle C1 Elemete im Extremfall in Datensätzen befinden, aus denen schon drei Elemente gewählt wurden, selbst wenn man die Elemente des "Leittyps" erst nach der Auswahl der Sekundäretypen versucht auszuwählen. Es könnte zur Endlosscheife werden, da nun eine erneute Stichprobenauswahl vorgenommen enden müßte.
Pseudo-Code:
Gruppiere alle Typen in einer Matrix: AllData[0:maxRecs, 0:maxItems]
Zähle alle Elemente eines jeden Typs: NTyp[iRec,t]=SUM(AllData[iRecs,k=1..maxt]=Typ[t])
Berehcne Stichprobenumfang:
maxNSP=2*int(MAX(
SUM(NTyp(irec=1...maxRecs, refT));
SUM(SUM(NTyp(iref,Typ ohne refT)))/2+1)
'Auswahl der Stichproben vom Typ tx (=A1, B1, B2, C1,C2)
while nAx < SUM(NTyp(irec=1...maxRecs, tx))/2
wähle eine Element aus Typmenge Ax
bestimme einen Datensatznummer: irec=int(maxRecs*rnd())+1
enthält Datenzatz noch ien Element vom Typ tx: NTyp(irec, tx)>0, dann
enthält der Datensatz weniger als 3 Markierungen (nSel(irec)<3), dann
erhöhe Markierungszähler des Datensatzes: nSel(irec)=nSel(irec)+1
Selektiere Eintrag als Stichprobenmenge
Matrix SP[irec,nSel(irec))=Typ(tx)
erhöhe Typzähler nAx=nAx+1
vermindere Anzahl des Typs im Datensatz: NTyp(irec, tx)=NTyp(irec=, tx)-
wend
Im Feld SP sollten die Stichproben nach Datensatz geordnet aus denen sie entnommen wurden stehen.
Soweit meine ersten Grundgedanken zum Projekt. Vielleicht verstellen mir aber auch meine Überlegungen den richtigen Blick auf Deine Aufgabenstellung und deren einfach Lösungungsansatz; daher markiere ich die Frage als "noch offen".
Gruß,
Uwe
Anzeige
AW: Stichprobenziehung mit VBA
30.01.2007 21:08:49
Marcus
Danke ersteinmal Uwe,
es hilft ja häufig schon, mal eine andere Idee als die eigene zu hören...
Zu deinen Fragen:
- Handelt es sich hier um eine Zeitreihe für die die Information zeiliche Reihenfolge nicht verloren gehen darf? Sind immer alle Einträge eines Datensatzes gefüllt?
Die Zeile stellen eine zeitliche Reihenfolge da. Jede Zeile steht für einen Meßzeitpunkt; daher auch die 3 Stichproben pro Zeile. Es wird aber auch Datenausfälle geben; d.h. es kann vorkommen, dass einzelne Zellen in einer Zeile nicht ausgefüllt sind.
Zum Beispiel:
- Es esistieren von A1 (Leittyp) 11 Elemente in dem Gesmtumfang der Daten. Die Bedingung, dass dieser Typ 50% im Stichprobenumfang ausmacht, ergibt die Anzahl des Stichprobenumfangs, nämlich 2*(11*0,5) = 12 (ganzahlig auf die nächsthöhere, durch 2 teilbare Zahl aufgerundet).
Der Stichprobenumfang muss vorher festgelegt werden; im Beispiel auf 10 Einheiten begrenzt werden. Das hat zur Folge, dass 5 Einheiten dem Leittyp A1 und die restlichen den andern Typen entsprechen müssen. Hier gibt es nun noch 4 Resttypen; davon müssen min. 50%, also min. 2 Typen, berücksichtigt werden - es muss also sichergestellt werden, dass nicht 5 mal B1 gezogen wird.
Meine Idee sah so aus:
Schritt 1: Ziehe systematisch 5-mal Typ A1 aus der Matrix via Zufallsauswahl.
Schritt 2: Ziehe systematisch 5-mal Typ B1, B2, C1 oder C2 aus der Matrix via Zufallsausahl. Wenn mehr als insgesamt (also A1, B1, B2, C1, C2) 3 Ziehungen pro Zeile vollzogen wurden, lösche zufällig so viele dieser Ziehungen bis maximal 3 vorliegen - lösche jedoch nur Typen B1, B2, C1 oder C2.
Schritt 3 (optional): Wenn Ziehungen gelöscht wurden, dann ziehe so viele neue Zellen bis das Sample (n=10) vollständig ist; beachte hierbei, dass nur Zellen aus Zeilen gezogen werden in denen weniger als 3 Ziehungen vorliegen.
Das ist, wenn ich`s richtig sehe, deiner Idee nicht unähnlich; nur das ich noch das Löschen und Nachziehen drin habe. Oder glaubst du das geht so nicht?
Wenn`s geht, dann stelle ich mir die Frage: wie setze ich das um? Gibt es da eine grazile Lösung? Man könnte das natürlich ganz wuchtig machen, indem man die gezogen Zellen markieren und auszählen lässt - also quasi eine Sekundärtabelle zur Auswertung anlegt. Aber schlank wäre natürlich schöner...
Würde mich über noch mehr Unterstüzung freuen,
Marcus
Anzeige
AW: Stichprobenziehung mit VBA
30.01.2007 23:10:58
ingUR
Hallo, Marcus,
die Zusatzinformationen und Deine Erläuterungen haben da schon ein paar Vereinfachungen ermöglicht, die ich zuvor so nicht erkannte.
Ein Grundgerüst für eine VBA-Prozedur kann vielleicht folgender Modul-Programmcode verwendet werden:
Option Explicit
Const NSP As Long = 10 'Anzahl det Stichprobenelemente
Const PTYP As Integer = 1 'Leittyp / Primättyp
Const DATASHEET = "Tabelle1"
Const DATARANGE = "B2:F6"
Sub stichprobenN()
Dim ws As Worksheet
Dim Typ, AllData, refTyp, NTyp() As Long, nSel() As Integer
Dim maxt As Integer, t As Integer
Dim maxRec As Long, iRec As Long
Dim maxItem As Long, iItem As Long
Dim s As Integer, p As Integer
Dim TypP As Integer, maxSProben As Long, iProbe As Long, SProbe
Typ = Array("", "A1", "B1", "B2", "C1", "C2")
'Lese Tabelle
Set ws = Worksheets(DATASHEET)
AllData = ws.Range(DATARANGE).Value
maxt = UBound(Typ)
maxRec = UBound(AllData, 1)
maxItem = UBound(AllData, 2)
ReDim NTyp(maxRec, maxItem), sumNTyp(maxItem), nSel(maxRec)
'ermittle Anzahl des Vorkommens eines jeden Typs
For iRec = 1 To maxRec
'ermittle Häufigkeit der Typen in einem Datensatz
For iItem = 1 To maxItem
refTyp = AllData(iRec, iItem)
For t = 1 To maxItem
If refTyp = Typ(t) Then
NTyp(iRec, t) = NTyp(iRec, t) + 1 'Symmenbildung je Datensatz
sumNTyp(t) = sumNTyp(t) + 1 'Summenbildung je Typ
Exit For
End If
Next t
Next iItem
Next iRec
TypP = PTYP 'Primärtyp-Index
maxSProben = NSP
'Setze Stichprobenumfang und zulässige Anzahl einer jeden Teilmenge
' TypP:=50%, TypX:=50%/(maxt-1) auf nächst Ganzzahl aufgerundet
For t = 1 To maxt
If t = TypP Then
sumNTyp(t) = Int(maxSProben / 2)
Else
sumNTyp(t) = Int((maxSProben / 2) / (maxt - 1)) + 1
End If
Next t
'    'alternativ, wenn nur mindestens ein Element eines
'    'zweiten Sekundärtyps im Stichprobenumfang ausreicht
'    'neben bereits einem ausgewähltem Sekundärtyp
'    For t = 1 To maxt
'        If t = TypP Then
'            sumNTyp(t) = maxSProben / 2
'        Else
'            sumNTyp(t) = maxSProben / 2 - 1
'        End If
'    Next t
ReDim SProbe(maxRec, 3)
Randomize
'Zufallsziehungen von maxSProben/2-Elementen des Primärtyps
s = 0
While iProbe < maxSProben / 2
iRec = Int(maxRec * Rnd()) + 1
'sind aus dem Datensatz noch keine drei Elemente gewählt?
If nSel(iRec) < 3 Then
'enthält Datensatz (noch) ein Element vom Typ t
If NTyp(iRec, TypP) > 0 Then
iProbe = iProbe + 1
nSel(iRec) = nSel(iRec) + 1
'füge Element der Stichprobe zu
SProbe(iRec, nSel(iRec)) = Typ(TypP)
NTyp(iRec, TypP) = NTyp(iRec, TypP) - 1
End If
End If
Wend
'Zufallsziehungen von maxSProben/2-Elementen aus der Menge der Sekundärtypen
iProbe = 0
While iProbe < maxSProben / 2
iRec = Int(maxRec * Rnd()) + 1
'sind aus dem Datensatz noch keine drei Elemente gewählt?
If nSel(iRec) < 3 Then
'wähle einen Sekundärtyp
t = TypP
While t = TypP Or t > maxt
t = Int(maxt * Rnd()) + 1
Wend
'enthält Datensatz (noch) ein Element vom Typ t und
'sind noch nicht die maximal mögliche Anzahl der Elemente
'vom Typ t gezogen
If NTyp(iRec, t) > 0 And sumNTyp(t) > 0 Then
iProbe = iProbe + 1
nSel(iRec) = nSel(iRec) + 1
'füge Element der Stichprobe zu
SProbe(iRec, nSel(iRec)) = Typ(t)
NTyp(iRec, t) = NTyp(iRec, t) - 1
sumNTyp(t) = sumNTyp(t) - 1
End If
End If
Wend
For iRec = 1 To maxRec
p = 0
For t = 1 To 3
ws.Cells(iRec + 1, 8 + t) = ""
If SProbe(iRec, t) > 0 Then
p = p + 1
ws.Cells(iRec + 1, maxt + 2 + p) = SProbe(iRec, p)
End If
Next t
Next iRec
Set ws = Nothing
End Sub
In welchem Anwendungsbereich benötigt man eine derart geziehlte Stichprobenauswahl, Marcus?
Gruß,
Uwe
Anzeige
AW: Stichprobenziehung mit VBA
31.01.2007 19:47:12
Marcus
Hallo Uwe,
das sieht wirklich gut aus. Ich werd`s in den kommenden Tagen ausprobieren und gebe dir dann eine Rückmeldung. Das Ganze dient einem Evaluationsprojekt. Das komplexe Design der Stichprobe ist knappen Ressourcen geschuldet. :) All die gezogenen Fälle müssen individuell von einer je Person durch Beobachtung evaluiert werden. Es gibt aber nur 3 Personen die das machen können; daher nur drei zeitgleiche Stichproben.
Vielen Dank soweit ersteimal und viele Grüße,
Marcus

32 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige