¿Cómo especificar una matriz de correlación en Profiler for Simulation?Hola,
Estoy escribiendo un script para crear datos normales multivariados con un número específico de filas, vectores de media/desviación estándar y una estructura de correlación a partir de un conjunto de datos de muestra. Me gustaría aprovechar el Simulador en la plataforma Profiler para generar la tabla de datos a través de los siguientes pasos:
- Calcule la media muestral y la desviación estándar para cada variable.
- Genere una matriz de correlación a partir de datos de muestra.
- Simule datos multivariados utilizando las estadísticas de resumen de (1) y (2).
Actualmente, mi script genera la tabla de datos simulados con las medias y desviaciones estándar apropiadas para cada variable, pero no logro mantener correctamente la estructura de correlación entre variables. Creo que la causa de mi problema es cómo especifico el [ NxN correlaciones] con Correlaciones X usando una variable en lugar de especificar explícitamente la matriz de correlación (por ejemplo, [1 0.3 0, 0.3 1 0, 0 0 1]), pero mis habilidades para solucionar problemas me han dejado sin solución. El script actual y el resultado esperado frente al real se proporcionan a continuación. Cualquier sugerencia sobre cómo lograr estos pasos es bienvenida:
JSL:
names default to here(1);
Try( Close( Data Table(dt) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
ncol = NCol(dt);
//Dialog Window.
Dlg = New Window("New Window",
<< Modal,
BorderBox(left(3), top(2),
V List Box(
TextBox("Simulate multivariate data"),
HListBox(
VListBox(
PanelBox("Select variables",
colListData = ColListBox(all,nLines,(min(ncol,10)))
),
),
PanelBox("Cast Selected Variables",
LineupBox(NCol(2), Spacing(3),
ButtonBox("Variables", colListY << Append(colListData << Get Selected)),
colListY = ColListBox(nLines(6), "numeric"))
),
//specifications - not in use.
PanelBox("Enter Specifications",
Spacer Box(Size(10, 1)),
HListBox(
VListBox(
Spacer Box(Size(5, 10)),
lsl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl4 = Number Edit Box(, 3)
),
SpacerBox(Size(10,10)),
VListBox(
Spacer Box(Size(5, 10)),
usl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl4 = Number Edit Box(, 3)
)
),
),
PanelBox("Action",
LineupBox(NCol(1),
// OK button
Button Box("OK",
lsl_mat = J(4,1, .);
lsl_mat[1] = Eval(lsl1 << Get);
lsl_mat[2] = Eval(lsl2 << Get);
lsl_mat[3] = Eval(lsl3 << Get);
lsl_mat[4] = Eval(lsl4 << Get);
usl_mat = J(4,1, .);
usl_mat[1] = Eval(usl1 << Get);
usl_mat[2] = Eval(usl2 << Get);
usl_mat[3] = Eval(usl3 << Get);
usl_mat[4] = Eval(usl4 << Get);
// Store summary statistics
tpListY = colListY << Get Items;
tpMean = J(4, 1, 0);
tpSD = J(4, 1, 0);
for (i=1, i <= nitems(tpListY), i++,
one_col = tpListY[i];
Meani = Col Mean(Column(dt, one_col));
SDi = Col Std Dev(Column(dt, one_col));
tpMean[i] = Meani;
tpSD[i] = SDi;
);
Dlg << CloseWindow
),
// Cancel button
Button Box("Cancel", Dlg << CloseWindow),
Spacer Box(Size(10,10)),
// Remove button
Button Box("Remove", collistY << RemoveSelected)
)
),
)
)
)
);
//correlation matrix
corr = multivariate(
Y(Eval List(tpListY)),
estimation method("Row-wise"),
matrix format("Square"),
scatterplot matrix(0)
);
corr.run = corr << run;
corr.rep = corr.run << report;
corr.mat = corr.rep["Correlations"][matrix box(1)] << get(1);
//only used to launch profiler
prof.x = J(2,4 ,1);
prof.tbl = as table(prof.x, << column names(tpListY), << invisible);
prof.tbl << new column("Y",
Formula( :TP1 + :TP2 + :TP3 + :TP4)
);
prof.tbl = current data table();
random reset(1234);
//specify multivariate data from summary statistics
sim.design = Profiler(
Y(:Y),
Invisible
);
sim.design << Simulator(
1,
Factors(
TP1 << multivariate( tpMean[1], tpSD[1]),
TP2 << multivariate( tpMean[2], tpSD[2]),
TP3 << multivariate( tpMean[3], tpSD[3]),
TP4 << multivariate( tpMean[4], tpSD[4]),
),
X Correlations(
1,
tpListY,
corr.mat
),
N Runs(10000)
);
//Make data table
report( sim.design )["Simulate to Table"][button box( 1 )] << click( 1 );
sim.dt = data table( 1 );
sim.dt << set name( "Simulated multivariate data" );
sim.dt << delete columns({"Y","Obj"});Salida esperada vs. real:
expectedvsactualexpectedvsactualesperadovsactual
Automatización y secuencias de comandosExploración y visualización de datosRe: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
¡Muy lindo! Sin duda, me gusta el código más corto y elegante (aunque no soy tan bueno en eso). Por curiosidad, ¿ha verificado si los resultados de trabajar con la media y las desviaciones estándar y la matriz de correlación dan (aproximadamente) los mismos datos simulados que trabajando solo con la media y la matriz de covarianza?
Lamento que este otro enfoque no haya funcionado, pero me alegro de que haya encontrado una buena solución que es portátil a otros datos con los que está trabajando. Estoy probando algunos modelos en los datos simulados para ver cómo se comparan con los modelos creados con los datos reales. Puedo ver dónde esto podría ser muy útil cuando el conjunto de datos reales es relativamente pequeño y los datos simulados pueden brindarle la oportunidad de al menos crear un modelo no tan terrible que pueda implementarse temprano y luego actualizarse a medida que ingresan más datos. . Es decir, en lugar de esperar durante meses a que se genere un conjunto de datos lo suficientemente grande. A veces, vale la pena tener un modelo en su lugar, incluso si no es "perfecto".
¡Gracias por la discusión y los puntos de aprendizaje!
¡Buena suerte!,
SD
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @SDF1 ,
Nunca hubiera pensado en ese enfoque, muy bien hecho. En cuanto a la ventana de diálogo, creo que tienes razón, tendré que echarle un vistazo más de cerca. Resultó ser un dolor de cabeza menor evitar la plataforma Profiler por completo, aunque fue una buena idea, pero no funcionó para mí. Aquí está el mismo resultado pero con menos complicaciones (similar a los pasos que tomo para implementar en R) y solo se necesitan como entradas el vector medio y la matriz de covarianza.
//tpListY is variables.<BR /><BR />cov = multivariate(
Y(eval list(tpListY)),
estimation method("Row-wise"),
matrix format("Lower Triangular"),
scatterplot matrix(1)
);
cov << covariance matrix(1);
cov.run = cov << run;
cov.rep = cov.run << report;
cov.mat = cov.rep["Covariance Matrix"][matrix box(1)] << get(1);
random reset(1234);
//generate X = (X1, . . . , Xn) where X ∼ MNn(µ, Σ) using the Cholesky decomposition of Σ
//to find (nxn) matrix, C, such that C*C` = Σ.
//let Z = (Z1, . . . , Zn)` where the Zi’s are IID N(µ, 1) for i = 1, . . . , n.
//mean.M is mean vector.
sim.n = 1e4;
dummy.mat = j(1,sim.n,1);
mean.mat = mean.M*dummy.mat;
n.means = n row(mean.M);
sim.C = cholesky(cov.mat);
sim.Z = j(n.means, sim.n, random normal());
sim.X = sim.C*sim.Z;
sim.X2 = sim.X + mean.mat;
sim.Xt = transpose(sim.X2);
as table(sim.Xt, << column names(tpListY));
Prefiero usar menos código para hacer el mismo trabajo, así que esto fue más atractivo que la ruta Profiler. Esperemos que esto haga que sea más fácil de implementar en otros lugares.
Gracias de nuevo,
eangello
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Creo que he podido elaborar un script escalable a N columnas. doy @EM una GRAN cantidad de crédito por ayudar a generalizar la porción de correlación del Profiler. ese hilo es aquí .
Hay dos secuencias de comandos, una versión independiente como la que implementó, pero sin las variables adicionales que tenía en su publicación original, así como una secuencia de comandos que puede ejecutarse desde una tabla de datos. El independiente está debajo y el que se ejecuta desde la tabla de datos está en la tabla de datos Gendt.jmp. Funciona tanto con su tabla de datos con 4 columnas como con la otra tabla de datos que hice con 11 columnas. También intenté generalizar el script independiente para tablas de datos con otros tipos de columnas.
Names Default To Here( 1 );
// Expression to clear all current settings
clearRoles = Expr( ColListY << RemoveAll );
// Expression to store the current settings in global variables
recallRoles = Expr(
::ycolRecall = ColListY << GetItems
);
//get data table
Try( Close( Data Table( dt ) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
//Find the number of columns in the data table
ncol = N Col( dt );
ColList = dt << Get Column Names( Numeric, Continuous );
//Dialog Window.
Dlg = New Window( "New Window",
<<RETURN result=""></RETURN>
Además, creo que el error del cuadro de botones que recibe tiene que ver con <<< Return Result, y ya no recibo el error. También incluí un botón de recuperación, pero no es necesario que lo tengas.
Espero que esto ayude, esto fue realmente genial y aprendí mucho de él. ¡Sé que definitivamente podré usar esto para mi trabajo!
¡Gracias!,
SD
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Eso es exactamente lo que pasó por mi mente cuando me di cuenta de lo que querían hacer con la estructura de correlación. Me gustaría tomar prestada su idea y modificarla para algunos de los problemas específicos que estoy enfrentando. He publicado en otro hilo sobre generalizar a N entradas. Creo que estoy bastante cerca, pero no del todo. Tengo dificultades para escalarlo cuando llamo a X Correlations() y establezco los valores de desarrollo medio y estándar para los factores.
Se adjunta una tabla de datos de maqueta y un script en el que estoy trabajando, todo basado en su script original. ¿Tal vez puedas encontrar los errores que estoy cometiendo? Me encantaría ver que esto funcione para un número arbitrario de columnas, sería muy útil para los datos históricos, como señala.
¡Gracias!,
SD
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @SDF1 ,
Con frecuencia simulo conjuntos de datos multivariados con fines de modelado (ajuste de modelos entre ellos), generalmente en función de algunos parámetros históricos. Este script fue solo una solución simple para servir estos datos simulados. No tengo un caso de uso específico en este momento, pero tengo la intención de escalar este script a n-dimensiones y potencialmente usarlo como un funcional módulo Puedo incorporar en scripts más extensos que usan técnicas de muestra grande. Dadas las limitaciones con el envío de vectores de media/sd y matriz de correlación a la plataforma Profiler, probablemente recurriré a escribir explícitamente las operaciones lineales para escalar la simulación a n dimensiones.
Saludos,
eangello
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Gran solución, y desearía haber recordado hacerlo de esa manera. Tuve que hacer algo similar al escribir un guión para automatizar algunos ajustes del modelo. Los caracteres EvalInsert() y escape para comillas y ^^ para insertar valores fueron muy útiles. Simplemente no lo uso tan a menudo y me olvidé de esa forma particular de hacer las cosas.
Por curiosidad, ¿por qué necesita generar datos simulados como ese con la estructura de correlación especificada? Estoy bastante interesado, ya que me ha dado algunas ideas sobre cómo incorporar eso en algunas cosas en las que estoy trabajando.
¡Gracias!,
SD
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @SDF1 ,
Gracias por la ayuda para solucionar problemas, muy apreciada. Jugué con funciones similares como Eval, Eval Expr( Expr(x) ) , y Evalinsert y encontró una solución forzando la(s) variable(s) de columna y matriz para evaluar antes de enviar a Profiler (que Correlaciones X parece aceptar). Apliqué la misma solución anterior para que mi generador de perfiles sea flexible a diferentes nombres de columna. Ahora mi estructura de correlación se mantiene en los datos simulados.
new.design = evalinsert(
"\[sim.design << Simulator(
1,
Factors(
Name( "^col1^" ) << multivariate( tpMean[1], tpSD[1]),
Name( "^col2^" ) << multivariate( tpMean[2], tpSD[2]),
Name( "^col3^" ) << multivariate( tpMean[3], tpSD[3]),
Name( "^col4^" ) << multivariate( tpMean[4], tpSD[4]),
),
X Correlations(
1,
^tpListY^,
^corr.mat^
),
N Runs(10000)) ]\");
eval(parse(new.design));
Gracias de nuevo,
EE. UU.
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Gracias por la tabla de datos. Puedo recrear tu problema como lo mencionas. Una cosa que noto es que cuando ejecuta el simulador, no crea el histograma al lado del generador de perfiles, no como el ejemplo de la banda de rodadura en el índice de ayuda en X Correlations.
Creo que pasan dos cosas:
1. llamando a tpListY
2. llamando a corr.mat
No estoy seguro de por qué, pero creo que debe "deletrear" explícitamente la lista de correlaciones X en su código y esto incluye la matriz de correlación, por lo que en lugar de llamar a tpListY, debe reemplazar eso con {TP1, TP2 , TP3, TP4}. Del mismo modo, debe colocar la matriz de correlación real de 4x4 (o NxN) entre los corchetes [].
Pensé que hacer algo como Parse(tpListY[1]) funcionaría, pero no puedo hacer que funcione, incluso con un Eval() envuelto alrededor. Solo puedo hacer que funcione automáticamente si ingreso el código JSL como {TP1, TP2, TP3, TP4}. Tenga en cuenta que cuando coloca la matriz de correlación NxN, en realidad usa el triángulo inferior izquierdo de la matriz para completar la tabla.
También pensé que llamar a los elementos de corr.mat podría funcionar, como en corr.mat[1], etc., pero eso tampoco funciona. Si intento eso, obtengo un error de token de matriz no válido, y no estoy seguro de por qué, porque los elementos de corr.mat son números.
El siguiente código (modifiqué su función para cambiarla un poco) funciona para proporcionar el resultado esperado, pero no ayuda con su deseo de expandirse de un sistema 4x4 a un sistema NxN.
names default to here(1);
Try( Close( Data Table(dt) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
ncol = NCol(dt);
//Dialog Window.
Dlg = New Window("New Window",
<< Modal,
BorderBox(left(3), top(2),
V List Box(
TextBox("Simulate multivariate data"),
HListBox(
VListBox(
PanelBox("Select variables",
colListData = ColListBox(all,nLines,(min(ncol,10)))
),
),
PanelBox("Cast Selected Variables",
LineupBox(NCol(2), Spacing(3),
ButtonBox("Variables", colListY << Append(colListData << Get Selected)),
colListY = ColListBox(nLines(6), "numeric"))
),
//specifications - not in use.
PanelBox("Enter Specifications",
Spacer Box(Size(10, 1)),
HListBox(
VListBox(
Spacer Box(Size(5, 10)),
lsl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl4 = Number Edit Box(, 3)
),
SpacerBox(Size(10,10)),
VListBox(
Spacer Box(Size(5, 10)),
usl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl4 = Number Edit Box(, 3)
)
),
),
PanelBox("Action",
LineupBox(NCol(1),
// OK button
Button Box("OK",
lsl_mat = J(4,1, .);
lsl_mat[1] = Eval(lsl1 << Get);
lsl_mat[2] = Eval(lsl2 << Get);
lsl_mat[3] = Eval(lsl3 << Get);
lsl_mat[4] = Eval(lsl4 << Get);
usl_mat = J(4,1, .);
usl_mat[1] = Eval(usl1 << Get);
usl_mat[2] = Eval(usl2 << Get);
usl_mat[3] = Eval(usl3 << Get);
usl_mat[4] = Eval(usl4 << Get);
// Store summary statistics
tpListY = colListY << Get Items;
tpMean = J(4, 1, 0);
tpSD = J(4, 1, 0);
for (i=1, i <= nitems(tpListY), i++,
one_col = tpListY[i];
Meani = Col Mean(Column(dt, one_col));
SDi = Col Std Dev(Column(dt, one_col));
tpMean[i] = Meani;
tpSD[i] = SDi;
);
Dlg << CloseWindow
),
// Cancel button
Button Box("Cancel", Dlg << CloseWindow),
Spacer Box(Size(10,10)),
// Remove button
Button Box("Remove", collistY << RemoveSelected)
)
),
)
)
)
);
//correlation matrix
corr = multivariate(
Y(Eval List(tpListY)),
estimation method("Row-wise"),
matrix format("Square"),
scatterplot matrix(0)
);
corr.run = corr << run;
corr.rep = corr.run << report;
corr.mat = corr.rep["Correlations"][matrix box(1)] << get(1);
//only used to launch profiler
prof.x = J(200,4 ,1);
prof.tbl = as table(prof.x, << column names(tpListY), << invisible);
prof.tbl << new column("Y",
Formula( :TP1+:TP2^2-:TP3+:TP4*Random Normal(0,2))
);
prof.tbl = current data table();
random reset(1234);
//specify multivariate data from summary statistics
sim.design = Profiler( Y( :Y ), Invisible );
sim.design << Simulator(
1,
Factors(
TP1 << multivariate( tpMean[1], tpSD[1] ), TP2 << multivariate( tpMean[2], tpSD[2] ),
TP3 << multivariate( tpMean[3], tpSD[3] ), TP4 << multivariate( tpMean[4], tpSD[4] ),
),
Responses( Y << No Noise ),
Automatic Histogram Update( 1 ),
X Correlations( 1, {TP1, TP2, TP3, TP4},
[1 0.6401843997 0.670478399654806 0.6405126152, 0.6401843997 1 0.9443055859 0.8815992957, 0.6704783997 0.9443055859 1 0.9355872238, 0.6405126152 0.8815992957 0.9355872238 1]
),
N Runs( 10000 ),
Simulate
);
//Make data table
report( sim.design )["Simulate to Table"][button box( 1 )] << click( 1 );
sim.dt = data table( 1 );
sim.dt << set name( "Simulated multivariate data" );
sim.dt << delete columns({"Y","Obj"});Debe haber una manera de hacerlo, ya que puede llamar a los elementos de tpMean y tpSD para completar el ruido multivariante de los factores. Creo que alguien con más experiencia en JSL podría ser necesario para comentar sobre eso.
Por último, creo que tiene razón sobre uno de los cuadros de botones, pero tampoco pude identificarlo exactamente: ¡estaba más enfocado en tratar de resolver los problemas de tpListY y corr.mat! 
Me interesa mucho lo que averigües.
Buena suerte,
SD
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @SDF1 ,
No hice mi diligencia debida antes de publicar: aquí hay una muestra de 10 filas de los datos de muestra (4 X; TP1-TP4). La secuencia de comandos actual está restringida a 4 variables, pero espero poder escalar esto a norte variable en el futuro. Esta tabla de datos de muestra recreará mi problema. Creo que el error de nombre sin resolver proviene del cuadro de diálogo (tal vez cancelar/eliminar botones), pero no he encontrado la causa principal.
Gracias,
EE. UU.
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Esta es una pregunta interesante, y me gustaría tratar de ayudar si puedo, pero no puedo reproducir su problema. Cuando intento ejecutar su secuencia de comandos, me pide que abra una tabla de datos del directorio de datos de muestra. Un problema aquí es que no sé con qué tabla de datos está trabajando y no obtendré el mismo problema. ¿Puede proporcionar la tabla de datos con la que está trabajando?
Si selecciono una tabla de datos de los datos de muestra, por ejemplo, el archivo 2D Gaussian process example.jmp, la siguiente ventana de diálogo solicita convertir las columnas en roles, pero luego, cuando hago clic en Aceptar, aparece el error de que hay un problema sin resolver. nombre Nombre en exceso o evaluación de 'Botón', Botón(-1) /*###*/. Luego, surge otro error de la línea 124 en su código donde no le gusta el comando de envío sim.design << Simulator() .
Aparentemente, tienes una tabla de datos donde esto funciona. ¿Puedes compartirlo? ¿O brinde más detalles sobre la tabla que está utilizando para generar el resultado que mostró en su publicación?
¡Gracias!,
SD