¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola,
Estoy escribiendo un script para crear datos normales multivariados con un número específico de filas, vectores de desviación media / estándar y 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 adecuadas para cada variable, pero no puedo mantener la estructura de correlación entre las variables correctamente. Creo que la causa de mi problema es cómo especifico el [ NxN correlaciones] con X Correlaciones 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 de resolución de problemas me han dejado sin solución. La secuencia de comandos actual y la salida esperada frente a la real proporcionada 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 frente a real:
esperadovsactual
Tabla de datosScriptingRe: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Esta es una pregunta interesante y me gustaría intentar ayudar si puedo, pero no puedo reproducir su problema. Cuando intento ejecutar su script, 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 example.jmp del proceso gaussiano 2D, la siguiente ventana de diálogo solicita convertir columnas en roles, pero luego, cuando hago clic en Aceptar, aparece el error de que hay un nombre Nombre en exceso o evaluación de 'Botón', Botón (-1) / * ### * /. Luego, aparece otro error de la línea 124 en su código donde no le gusta el comando sim.design << Simulator () send.
Aparentemente, tienes una tabla de datos donde esto funciona. ¿Puedes compartirlo? ¿O da más detalles sobre la tabla que estás usando para generar el resultado que mostraste en tu publicación?
¡Gracias!,
DS
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @DiedrichSchmidt ,
No cumplí con mi diligencia debida antes de publicar: aquí hay una muestra de 10 filas de los datos de muestra (4 X; TP1-TP4). El script actual está restringido a 4 variables, pero espero poder escalar esto a norte variables en el futuro. Esta tabla de datos de muestra volverá a crear 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 raíz.
Gracias,
EA
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 mencionas. Una cosa que estoy notando es que cuando ejecuta el simulador, no crea el histograma al lado del generador de perfiles, no como el ejemplo de neumáticos en el índice de ayuda sobre correlaciones X.
Creo que están sucediendo dos cosas:
1. llamar a tpListY
2. llamando a corr.mat
No estoy seguro de por qué, pero creo que debe "deletrear" explícitamente la lista de las correlaciones X en su código y esto incluye la matriz de correlación., Así que en lugar de llamar a tpListY, debe reemplazarla con {TP1, TP2 , TP3, TP4}. De manera similar, debe colocar la matriz de correlación real de 4x4 (o NxN) allí entre los corchetes [].
Pensé que hacer algo como Parse (tpListY [1]) funcionaría, pero no puedo hacerlo funcionar, incluso con un Eval () envuelto alrededor. Solo puedo hacer que funcione automáticamente si introduzco 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 muy 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 forma de hacerlo, ya que puede llamar a los elementos de tpMean y tpSD para completar el ruido multivariado de los factores. Creo que podría necesitarse alguien con más experiencia en JSL 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!;)
Estoy realmente interesado en lo que averigües.
Buena suerte,
DS
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @DiedrichSchmidt ,
Gracias por la ayuda para la resolución de problemas, muy apreciada. Jugué con funciones similares como Eval, Eval Expr (Expr (x) ) , y Evaluar y encontré una solución al forzar la (s) columna (s) y la (s) variable (s) de matriz a evaluar antes de enviar a Profiler (que X Correlaciones parece aceptar). Apliqué la misma solución anterior para que mi Profiler 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,
EA
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Gran solución, y desearía haberme acordado de hacerlo de esa manera. Tuve que hacer algo similar al escribir un script para automatizar algunos ajustes de modelo. EvalInsert () y los caracteres de escape para las comillas y ^^ para insertar valores fue muy útil. Simplemente no lo uso con tanta frecuencia 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!,
DS
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @DiedrichSchmidt ,
Con frecuencia simulo conjuntos de datos multivariados con fines de modelado (ajuste de modelos entre ellos), generalmente basados en algunos parámetros históricos. Este script fue solo una solución simple para entregar 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 funcional módulo Puedo incorporar en scripts más extensos que usan técnicas de muestra grande. Dadas las restricciones con el envío de vectores de media / sd y la 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 ,
Eso es exactamente lo que pasó por mi mente cuando me di cuenta de lo que querías hacer con la estructura de correlación. Me gustaría tomar prestada su idea y modificarla a algunos de los problemas específicos que estoy enfrentando. Publiqué en otro hilo sobre la generalización a N entradas. Creo que estoy bastante cerca, pero no del todo. Tengo dificultades para escalarlo cuando llamo a las correlaciones X () 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. ¿Quizás 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!,
DS
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @eangello ,
Creo que he podido elaborar un script que es escalable a N columnas. doy @Sra una GRAN cantidad de crédito por ayudar a generalizar la parte 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 se puede ejecutar desde una tabla de datos. El independiente está a continuación y el que se ejecutará 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 la << llamada modal para la ventana de diálogo. Lo reemplacé con << Devolver resultado 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, fue realmente genial y aprendí mucho de él. ¡Sé que definitivamente podré usar esto para el trabajo que hago!
¡Gracias!,
DS
Re: ¿Cómo especificar una matriz de correlación en Profiler para simulación?Hola @DiedrichSchmidt ,
Nunca hubiera pensado en ese enfoque, bien hecho. En cuanto a la ventana de diálogo, creo que tienes razón, tendré que mirar más de cerca. Resultó ser un dolor de cabeza menor evitar la plataforma Profiler por completo, aunque fue una buena idea que no funcionó para mí. Aquí está el mismo resultado pero con menos alboroto (similar a los pasos que doy para implementar en R) y solo el vector medio y la matriz de covarianza necesarios como entradas.
//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 en lugar de la ruta Profiler. Es de esperar que esto facilite la implementación en otros lugares.
Gracias de nuevo,
eangello