Tiempos superpuestosDigamos que tengo dos mesas. Tabla A y Tabla B. Tanto la tabla A como la B tienen horas de inicio y finalización de eventos. Quiero generar una nueva tabla que contenga solo eventos de la tabla B que ocurren durante el mismo período de tiempo que los eventos en la tabla A. ¿Hay una manera fácil de hacer esto con JSL?
Re: tiempos superpuestos¡Esto se ejecuta mucho más rápido, y hace exactamente lo que necesito! También aprendí mucho sobre JMP en el proceso. ¡¡¡Muy apreciado!!!Re: tiempos superpuestosPodría usar un controlador de estado de fila (ver más abajo). En la medida en que las coincidencias se conserven en la "Tabla B", uno debería preocuparse por actualizarlas cuando cambien los datos de la "Tabla B" o "Tabla A". Además, aunque la vinculación sea de concepto bidireccional, si intenta agregar un controlador de estado de fila correspondiente a la "Tabla A", tal vez no sea sorprendente que interfieran entre sí.
Usando este código, las selecciones en 'Tabla B' se propagarán a 'Tabla 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: tiempos superpuestos¡Gracias! Ahora he hecho que la matriz asociativa funcione, y es MUCHO más rápido que lo que estaba haciendo antes (es decir, 2 minutos frente a 2 horas).
¿Hay alguna manera de tomar la matriz asociativa y usarla para seleccionar automáticamente los números de fila correspondientes en la Tabla B?
Re: tiempos superpuestosTBH, me tomó algunos intentos (y un bolígrafo y papel) obtener la lógica correcta. Simplemente dibuje dos segmentos de línea en todas las diversas configuraciones (incluido cuando A está totalmente contenido en B, o viceversa). En realidad, es por eso que agregué los gráficos para estar seguro de que lo hice bien.
El uso de operaciones matriciales le permite vectorizar cosas, lo que generalmente es más rápido. En términos de la sintaxis, matA [0,1] (matA [0,2]) contiene todos los puntos de inicio (final) para los segmentos de línea denotados como 'A'. La función 'Loc ()' devuelve un vector de columna que da los números de fila en matA para los cuales se cumple la condición lógica.
Como mencionó Dan, puede usar <= instaed of
Re: tiempos superpuestosGracias por el enfoque interesante. Estoy tratando de envolver mi cabeza alrededor de la siguiente línea:
matchesInA = Loc((matA[0,1] < endB) & (startB < matA[0,2]));
¿Qué está haciendo y cómo funciona? ¡Aprecio tu ayuda!
Re: tiempos superpuestosCreo que las condiciones de superposición en las soluciones son ligeramente diferentes: la condición de matriz no cuenta la superposición si los dos intervalos solo tocan (<=), y Select Where () no cuenta un intervalo B que contenga totalmente una A intervalo. De cualquier manera, creo que el enfoque de la matriz será más rápido, pero ambos se atascarán en tablas muy grandes. Hacerlo mucho mejor requeriría una cierta clasificación y estructuras de datos como la Árbol de intervalo . Hacer eso desde JSL podría ser más costoso que los métodos de fuerza bruta.
Re: tiempos superpuestosEsto podría ser mejor. Utiliza valores de tiempo enteros, pero eso está bien.

.
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: tiempos superpuestosPara tu información, aquí es cómo lo estoy haciendo ahora.
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
);
);Desafortunadamente, la función tarda mucho tiempo cuando se trabaja con grandes datos de datos. ¿Hay alguna manera mejor?
Re: tiempos superpuestosSí, ambas tablas tienen una hora de inicio y finalización para cada evento. Así que necesito una solución que encuentre eventos en la tabla B que estén dentro o superpuestos por eventos en la tabla A.
Re: tiempos superpuestosEdit: Probablemente resolví un problema diferente al que usted describe. En su ejemplo, ¿cada fila tiene un (inicio, final) y desea intersecar filas en la tabla B con todas las filas en la tabla A? En mi ejemplo, solo hay un colectivo (inicio, fin) para la tabla.
Respuesta original:
Aquí hay una forma de crear la nueva tabla:
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");