Überlappende ZeitenIch habe zwei Tische. Tabelle A und Tabelle B. Beide Tabellen A und B haben Ereignisstart- und Endzeiten für Ereignisse. Ich möchte eine neue Tabelle generieren, die nur Ereignisse aus Tabelle B enthält, die im gleichen Zeitraum wie Ereignisse in Tabelle A auftreten. Gibt es eine einfache Möglichkeit, dies mit JSL zu tun?
Re: Überlappende ZeitenDas läuft so viel schneller und macht genau das, was ich brauche! Ich habe auch viel über JMP gelernt. Sehr geschätzt !!!Re: Überlappende ZeitenSie können einen Zeilenstatus-Handler verwenden (siehe unten). Insofern die Übereinstimmungen in 'Tabelle B' bestehen bleiben, müsste man sich Sorgen machen, diese zu aktualisieren, wenn sich die Daten in 'Tabelle B' oder 'Tabelle A' ändern. Auch wenn das Verknüpfen im Konzept bidirektional ist, wenn Sie versuchen, einen entsprechenden Zeilenstatus-Handler zu 'Tabelle A' hinzuzufügen, so kann es nicht überraschen, dass sie sich gegenseitig stören.
Wenn Sie diesen Code verwenden, wird die Auswahl in 'Tabelle B' zu 'Tabelle A' weitergeleitet:

NamesDefaultToHere(1);
dtA = NewTable("A",
NewColumn("Start", Numeric, Ordinal, Formula(RandomInteger(1, 20))),
NewColumn("End", Numeric, Ordinal, Formula(:Start + RandomInteger(1, 10)))
);
dtA << addRows(4);
dtA << runFormulas;
dtA:Start << deleteFormula;
dtA:End << deleteFormula;
dtB = NewTable("B",
NewColumn("Start", Numeric, Ordinal, Formula(RandomInteger(1, 20))),
NewColumn("End", Numeric, Ordinal, Formula(:Start + RandomInteger(1, 10)))
);
dtB << addRows(6);
dtB << runFormulas;
dtB:Start << deleteFormula;
dtB:End << deleteFormula;
// Get values into matrices
matA = dtA << getAsMatrix;
matB = dtB << getAsMatrix;
// Loop over the events in 'B' and compare each with all those in 'A' at the same time
matchesBtoA = AssociativeArray();
for(e=1, e<=NRow(matB), e++,
startB = matB[e,1];
endB = matB[e,2];
matchesInA = Loc((matA[0,1] < endB) & (startB < matA[0,2]));
matchesBtoA << InsertItem(e, matchesInA);
);
// Persist the matches in 'B', which becomes the 'master table'
dtB << New Column( "Rows in A", Expression);
for (r=1, r<=NRow(matB), r++,
Column(dtB, "Rows in A")[r] = matchesBtoA << getValue(r);
);
// This row state handler detects row selections in 'B' and selects rows in 'A'
fB =
function({sourceRows}, {Default Local},
selectedSourceRows = dtB << getSelectedRows;
rows2select = [];
for(r=1, r<=NRow(selectedSourceRows), r++,
rows2select = VConcat(rows2select, Column(dtB, "Rows in A")[selectedSourceRows[r]]);
);
dtA << clearSelect;
dtA << selectRows(rows2select)
);
// Assign row state handler to 'B'
obB = dtB << MakeRowStateHandler(fB);
Re: Überlappende ZeitenVielen Dank! Ich habe jetzt das assoziative Array zum Laufen gebracht, und es ist VIEL schneller als das, was ich vorher gemacht habe (dh 2 Minuten vs. 2 Stunden).
Gibt es eine Möglichkeit, das assoziative Array zu verwenden, um die entsprechenden Zeilennummern in Tabelle B automatisch auszuwählen?
Re: Überlappende ZeitenTBH, ich brauchte ein paar Versuche (und Stift und Papier), um die Logik richtig zu machen. Zeichnen Sie einfach zwei Liniensegmente in allen verschiedenen Konfigurationen (einschließlich, wenn A vollständig in B enthalten ist oder umgekehrt). Deswegen habe ich die Grafiken hinzugefügt, um sicher zu sein, dass ich es richtig verstanden habe!
Mit Matrixoperationen können Sie Dinge vektorisieren, was in der Regel schneller ist. In Bezug auf die Syntax enthält matA [0,1] (matA [0,2]) alle Anfangs- (End-) Punkte für die als 'A' bezeichneten Liniensegmente. Die 'Loc ()' - Funktion gibt einen Spaltenvektor zurück, der die Zeilennummern in matA angibt, für die die logische Bedingung erfüllt ist.
Wie Dan bereits erwähnt hat, können Sie <= instaed of Re: Überlappende Zeiten
Danke für den interessanten Ansatz. Ich versuche, den Kopf um die folgende Zeile zu wickeln:
matchesInA = Loc((matA[0,1] < endB) & (startB < matA[0,2]));
Was macht es und wie funktioniert es? Ich schätze Ihre Hilfe!
Re: Überlappende ZeitenIch denke, die Überlappungsbedingungen in den Lösungen sind geringfügig unterschiedlich. Die Matrixbedingung zählt keine Überlappung, wenn sich die beiden Intervalle nur berühren (<=), und das Select Where () zählt kein B-Intervall, das ein A enthält Intervall. Ich glaube auf jeden Fall, dass der Matrix-Ansatz schneller sein wird, aber beide werden bei sehr großen Tabellen nachlassen. Um viel besser zu machen, müssten Sortierungen und Datenstrukturen wie die Intervallbaum . Dies von JSL aus zu tun, kann teurer sein als die Brute-Force-Methoden.
Re: Überlappende ZeitenDas könnte besser sein. Es verwendet ganzzahlige Zeitwerte, aber das ist in Ordnung.

.
NamesDefaultToHere(1);
dtA = NewTable("A",
NewColumn("Start", Numeric, Ordinal, Formula(RandomInteger(1, 20))),
NewColumn("End", Numeric, Ordinal, Formula(:Start + RandomInteger(1, 10)))
);
dtA << addRows(4);
dtA << runFormulas;
dtA:Start << deleteFormula;
dtA:End << deleteFormula;
dtB = NewTable("B",
NewColumn("Start", Numeric, Ordinal, Formula(RandomInteger(1, 20))),
NewColumn("End", Numeric, Ordinal, Formula(:Start + RandomInteger(1, 10)))
);
dtB << addRows(6);
dtB << runFormulas;
dtB:Start << deleteFormula;
dtB:End << deleteFormula;
// Get values into matrices
matA = dtA << getAsMatrix;
matB = dtB << getAsMatrix;
// Loop over the events in 'B' and compare each with all those in 'A' at the same time
matchesBtoA = AssociativeArray();
for(e=1, e<=NRow(matB), e++,
startB = matB[e,1];
endB = matB[e,2];
matchesInA = Loc((matA[0,1] < endB) & (startB < matA[0,2]));
matchesBtoA << InsertItem(e, matchesInA);
);
// Graphs
maxX = Maximum(Maximum(matA[0,2]), Maximum(matB[0,2]));
minX = Minimum(Minimum(matA[0,1]), Minimum(matB[0,1]));
NewWindow("Overlapping Intervals", << onClose(Close(dtA, NoSave); Close(dtB, NoSave)),
LineUpBox(NCol(2),
VListBox(
GraphBox(Title("Line Intervals in Table A"),
XScale(minX, maxX), YScale(0, NRow(matA)+1), YName("Row Number"), FrameSize(500, 210),
for(ii = 1, ii<=NRow(matA), ii++,
Line({matA[ii,1], ii}, {matA[ii,2], ii});
);
),
GraphBox(Title("Line Intervals in Table B"),
XScale(minX, maxX), YScale(0, NRow(matB)+1), YName("Row Number"), FrameSize(500, 210),
for(ii = 1, ii<=NRow(matB), ii++,
Line({matB[ii,1], ii}, {matB[ii,2], ii});
);
)
),
GraphBox(Title("Row numbers in Table B (in Table A) on the left (on the right)"),
XScale(0, 1), YScale(0, Maximum(NRow(matA), NRow(matB))+1), YName("Row Number"), FrameSize(500, 500),
for(ii = 1, ii<=NRow(matB), ii++,
lines = matchesBtoA << getValue(ii);
for(jj=1, jj<=NRow(lines), jj++,
Line({0, ii}, {1, lines[jj]});
);
);
)
)
);
Re: Überlappende ZeitenZu Ihrer Information, so mache ich es jetzt.
OverlappingEvents = Function( {PrimaryTableName, PrimaryTableStartTime, PrimaryTableEndTime, SecondaryTableName, SecondaryTableStartTime, SecondaryTableEndTime}, {},
SecondaryTableName << Clear Selection;
For(i = 1, i <= nrows(PrimaryTableName), i++,
::PrimaryEndTime = Column( PrimaryTableName, PrimaryTableEndTime )[i];
::PrimaryStartTime = Column( PrimaryTableName, PrimaryTableStartTime )[i];
SecondaryTableName << select where( ::PrimaryStartTime <= as column(SecondaryTableStartTime) & as column(SecondaryTableEndTime) <= ::PrimaryEndTime | ::PrimaryStartTime <= as column(SecondaryTableEndTime) <= ::PrimaryEndTime | ::PrimaryStartTime <= as column(SecondaryTableStartTime) <= ::PrimaryEndTime, Current selection("Extend") ); //select all events in secondary table that overlap or are within events on primary table
);
);Leider dauert die Funktion beim Arbeiten mit großen Datentabellen sehr lange. Gibt es einen besseren Weg?
Re: Überlappende ZeitenJa, beide Tabellen haben für jedes Ereignis eine Start- und Endzeit. Ich brauche also eine Lösung, die Ereignisse in Tabelle B findet, die sich in Ereignissen in Tabelle A befinden oder von diesen überlappt werden.
Re: Überlappende ZeitenEdit: Ich habe wahrscheinlich ein anderes Problem gelöst als Sie beschreiben. Hat jede Zeile in Ihrem Beispiel ein (Anfang, Ende) und Sie möchten Zeilen in Tabelle B mit allen Zeilen in Tabelle A schneiden? In meinem Beispiel gibt es nur ein Kollektiv (Anfang, Ende) für die Tabelle.
Ursprüngliche Antwort:
So erstellen Sie eine neue Tabelle:
seriesP = Open("$SAMPLE_DATA/Time Series/SeriesP.jmp");
seriesP_years = seriesP:Year << Get Values;
seriesP_min = Min(seriesP_years);
seriesP_max = Max(seriesP_years);
seriesR = Open("$SAMPLE_DATA/Time Series/SeriesR.jmp");
seriesR << Select Where(:Year >= seriesP_min & :Year <= seriesP_max);
seriesRsubset = seriesR << Subset("Selected Rows");