Temps de chevauchementDis que j'ai deux tables. Table A et Table B. Les tables A et B ont les heures de début et de fin des événements. Je souhaite générer une nouvelle table qui ne contient que les événements de la table B qui se produisent pendant la même période que les événements de la table A. Existe-t-il un moyen simple de procéder avec JSL?
Re: temps de chevauchementCela va beaucoup plus vite et fait exactement ce dont j'ai besoin! En outre, j'ai beaucoup appris sur JMP au cours du processus. Très appréciée!!!Re: temps de chevauchementVous pouvez utiliser un gestionnaire d'état de ligne (voir ci-dessous). Dans la mesure où les correspondances sont conservées dans le «tableau B», il faudrait se préoccuper de les mettre à jour lorsque les données du «tableau B» ou du «tableau A» changent. De même, même si le concept de liaison est bidirectionnel, si vous essayez d’ajouter un gestionnaire d’état de ligne correspondant à la «Table A», il n’est peut-être pas surprenant que ces derniers interfèrent les uns avec les autres.
En utilisant ce code, les sélections dans 'Table B' se propageront à 'Table A':

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: temps de chevauchementJe vous remercie! J'ai maintenant fait fonctionner le tableau associatif, et il est BEAUCOUP plus rapide que ce que je faisais auparavant (c.-à-d. 2 minutes vs 2 heures).
Est-il possible de prendre le tableau associatif et de l'utiliser pour sélectionner automatiquement les numéros de ligne correspondants dans le tableau B?
Re: temps de chevauchementTBH, il m'a fallu quelques tentatives (et un stylo et du papier) pour bien comprendre la logique. Dessinez simplement deux segments de ligne dans toutes les configurations (y compris lorsque A est entièrement contenu dans B, ou inversement). En fait, c’est la raison pour laquelle j’ai ajouté les graphiques pour être sûr d’avoir bien compris!
L'utilisation d'opérations matricielles vous permet de vectoriser les choses, ce qui est généralement plus rapide). En termes de syntaxe, matA [0,1] (matA [0,2]) contient tous les points de début (fin) des segments de ligne désignés par «A». La fonction 'Loc ()' renvoie un vecteur colonne indiquant les numéros de ligne dans matA pour lesquels la condition logique est remplie.
Comme Dan l'a mentionné, vous pouvez utiliser <= instaed of
Re: temps de chevauchementMerci pour l'approche intéressante. J'essaie de faire le tour de la ligne suivante:
matchesInA = Loc((matA[0,1] < endB) & (startB < matA[0,2]));
Que fait-il et comment fonctionne-t-il? J'apprécie ton aide!
Re: temps de chevauchementJe pense que les conditions de chevauchement dans les solutions sont légèrement différentes - La condition de matrice ne compte pas de chevauchement si les deux intervalles ne se touchent que (<=), et que Select Where () ne compte pas un intervalle B contenant entièrement un A intervalle. Quoi qu'il en soit, je pense que l'approche matricielle sera plus rapide, mais les deux vont s'enliser pour les très grandes tables. Pour faire beaucoup mieux, il faudrait un tri et des structures de données comme le Arbre d'intervalle . Faire cela depuis JSL pourrait être plus coûteux que les méthodes de force brute.
Re: temps de chevauchementCela pourrait être mieux. Il utilise des valeurs de temps entières, mais ce n'est pas grave.

.
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: temps de chevauchementFYI, voici comment je le fais maintenant.
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
);
);Malheureusement, la fonction prend beaucoup de temps lorsque vous travaillez avec de grandes tables de données. Y a-t-il un meilleur moyen?
Re: temps de chevauchementOui, les deux tables ont une heure de début et de fin pour chaque événement. J'ai donc besoin d'une solution qui trouve les événements de la table B qui sont à l'intérieur ou qui se chevauchent par des événements de la table A.
Re: temps de chevauchementEdit: J'ai probablement résolu un problème différent de celui que vous décrivez. Dans votre exemple, chaque ligne a-t-elle un (début, une fin) et vous voulez intersecter les lignes de la table B avec toutes les lignes de la table A? Dans mon exemple, il n'y a qu'un seul collectif (début, fin) pour la table.
Réponse originale:
Voici un moyen de créer la nouvelle table:
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");