Subseleccionar aleatoriamente en grupos y obtener mediaHola,
Tengo un conjunto de datos de ~2000 individuos estratificados por 3 categorías (género/edad/etnicidad). Quiero obtener valores "agrupados" para estos individuos tomando ~8 individuos de cada género/edad/etnicidad y encontrando el promedio. Una advertencia es que hay más individuos en ciertos contenedores de categoría que en los demás. Se adjunta un desglose de todas las personas que obtuve y su agrupación. Por ejemplo, la categoría 1-1-1 tiene 120 individuos, por lo que podría crear 8*15 grupos de individuos aleatorios a partir de estos. ¿Qué pasa si tengo un número que no es múltiplo de 8?
¿Cómo puedo hacer todo esto en un solo paso? Al final tendríamos alrededor de 200 piscinas.

secuencias de comandosRe: Subseleccionar aleatoriamente en grupos y obtener mediaNo estoy totalmente seguro de haber creado un script que haga lo que desea, pero puede ser un buen comienzo.Esto es lo que hace
- Encuentra el grupo de género/edad/etnicidad que tiene la población más pequeña.Este grupo será el limitador de cuántos grupos se pueden crear, ya que ninguna fila puede aparecer en más de un grupo.
- Luego intenta encontrar el tamaño del grupo que minimizó la cantidad de filas no incluidas para ese subgrupo.Lo hace subiendo el tamaño del grupo de 8 a 21 y encuentra el resto más pequeño (desperdicio).
- A continuación, crea una tabla de trabajo a partir de la tabla original.
- Recorre la mesa de trabajo,
- Crea una muestra aleatoria estratificada
- Agrega la nueva muestra a la tabla de datos del grupo final
- Elimina de la tabla de datos de trabajo, las filas que se seleccionaron para la última tabla de datos aleatorios en subconjuntos.
- Se repite tantas veces como sea posible para obtener la mayor cantidad posible de registros de subgrupos más pequeños en la tabla final de datos agrupados.
Aquí está el JSL
Names Default To Here( 1 );
dt = Current Data Table();
// Find smallest subgroup
Summarize( dt, subGroup = by( :age, :gender, :ethnicity ), size = Count( :age ) );
smallest = Min( size );
// Find best group size
minLost = 999999999;
minLostSize = .;
For( i = 8, i <= 21, i++,
If( Mod( smallest, i ) < minLost,
minLost = Mod( smallest, i );
minLostSize = i;
)
);
// Create a working data table
dt2 = dt << subset( selected rows( 0 ), selected columns( 0 ), output table( "Working" ) );
dt2 << New Column( "__row__", set each value( Row() ) );
// Create start of final data table
dt2 << select rows( 1 );
dtPool = dt2 << subset( selected rows( 1 ), selected columns( 0 ), output table( "Final" ) );
dtPool << select rows( 1 );
dtPool << delete rows;
dtPool << New Column( "Pool Number" );
thePoolNumber = 0;
// Create data pools
For( i = 1, i <= Floor( smallest / minLostSize ), i++,
dtTemp = dt2 << Subset(
Sample Size( minLostSize ),
Selected columns only( 0 ),
Stratify( :ethnicity, :Age, :Gender )
);
thePoolNumber = thePoolNumber + 1;
dtTemp << New Column( "Pool Number", set each value( thePoolNumber ) );
dtPool = dtPool << concatenate( dtTemp, append to first table( 1 ) );
// Remove selected rows from working table
dtRemove = dtTemp << subset( selected rows( 0 ), columns( __row__ ) );
dtRemove << New Column( "Delete", character, set each value( "Yes" ) );
dt2 = dt2 << Update( With( dtRemove ), Match Columns( :__row__ = :__row__ ) );
dt2 << select where( :Delete == "Yes" );
dt2 << delete rows;
dt2 << delete columns( :delete );
// Cleanup temporary tables
Close( dtTemp, nosave );
Close( dtRemove, nosave );
);
// Delete the Working data table
Close( dt2, nosave );
Probé esto en una tabla de datos de muestra que creé, por lo que puede tener algunos problemas con su tabla real.He anotado el código, por lo que espero que pueda aprender lo que he hecho y pueda hacer ajustes para que funcione exactamente como lo necesita.
Re: Subseleccionar aleatoriamente en grupos y obtener media
Hola Jim,
Este script da como resultado una tabla en blanco. Lo que espero obtener de esto es una nueva columna en la tabla de datos original llamada "Número de grupo". Una cosa a tener en cuenta es que la edad no es una variable numérica continua. Es una variable categórica entre los números 1 - 4.
Una vez que tengo todas las muestras en el conjunto de datos original clasificadas dentro de su grupo, puedo calcular el valor medio del grupo tomando la media de las ~8 muestras en el grupo.
Adjunto el archivo como referencia.
La mesa de trabajo tiene sentido en el guión; está creando una columna en la que cada fila tiene un valor único. La creación del conjunto de datos final conduce a una hoja de datos en blanco y no veo de dónde surge este error.
Re: Subseleccionar aleatoriamente en grupos y obtener mediaMi JSL se completa con éxito si el tamaño potencial del grupo se reduce a 6. Mi código requiere que se pueda extraer al menos 1 muestra de cada subgrupo, y dado que el subgrupo, 1 2 4 solo tiene 6 observaciones (filas), el El código que escribí para encontrar el mejor tamaño de muestra tuvo que modificarse para tener un tamaño de grupo de 6.
Pero independientemente de eso, aparentemente no entiendo cómo está determinando sus grupos.Estaba equiparando su grupo a una muestra aleatoria, con un tamaño de muestra dado, para cada subgrupo de datos.Esto resulta ser una suposición falsa de mi parte.
¿Está creando grupos de forma independiente para cada subgrupo?Es decir, para el subgrupo 1 1 1, hay 120 filas de datos.Si el tamaño del grupo es 8, ¿crea 15 grupos?Y luego, para el grupo 1 1 2 que tiene 50 filas, ¿crearía 6 grupos, sin seleccionar 4 filas para un grupo?
¿Es así como creas tus piscinas?
Aquí está el desglose de todos los subgrupos de Género/etnicidad/edad.

Mi JSL actual no hace lo que usted quiere. Por favor, deme una explicación más precisa de cómo crear grupos, y veré qué se debe hacer para armar un script viable.
Re: Subseleccionar aleatoriamente en grupos y obtener mediaHola Jim,
Los subgrupos se crean teniendo ~ 8 personas en cada grupo. Tienes razón con respecto al 1-1-1. Este grupo tiene 120 individuos, por lo que si tuviéramos que agrupar a estos individuos al azar, deberían encajar exactamente en 15 grupos. Para el grupo 1-1-2, que tiene 50 filas, crearía 6 grupos de 8 personas y los 4 restantes se colocarían en su propio grupo.
¿Tiene sentido? Queremos que todas las filas de la tabla de datos estén asociadas con un número de grupo específico.
Re: Subseleccionar aleatoriamente en grupos y obtener mediaA continuación se muestra un script que funciona en su tabla de datos de muestra, creando todos los grupos que desee.Tómese el tiempo para estudiar el guión para que pueda hacer las modificaciones que pueda necesitar para ajustarlo a su forma final.
Names Default To Here( 1 );
dt = Current Data Table();
// Set the size of the pools
poolSize = 8;
thePoolNumber = 0;
// Add row number to data table
dt << New Column( "__Row__", Set Each Value( Row() ) );
// Create a working data table
dt2 = dt << subset(
selected rows( 0 ),
columns( {"Gender", "Ethnicity", "Age", "__Row__"} ),
output table( "Working" )
);
// Create start of final data table
dt2 << select rows( 1 );
dtPool = dt2 << subset( selected rows( 1 ), selected columns( 0 ), output table( "Final" ) );
dtPool << select rows( 1 );
dtPool << delete rows;
dtPool << New Column( "Pool Number" );
thePoolNumber = 0;
// Create data pools
While( N Rows( dt2 ) >= poolSize,
// Draw a new sample
dtTemp = dt2 << Subset(
Sample Size( poolSize ),
Selected columns only( 0 ),
Stratify( :Gender, :Ethnicity, :Age )
);
// Calculate the new pool numbers
dtPoolCount = dtTemp << Summary(
Group( :Gender, :Ethnicity, :Age ),
Freq( "None" ),
Weight( "None" ),
Link to original data table( 0 )
);
// Get the current pool number
maxPool = Col Max( dtPool:Pool Number );
If( Is Missing( maxPool ),
maxPool = 0
);
// Add Pool Number to Pool Count table
dtPoolCount << New Column( "Pool Number", set each value( maxPool + Row() ) );
dtPoolCount << delete columns( N Rows );
// Set the current pool number in the current sample table
dtTemp = dtTemp << Update(
With( dtPoolCount ),
Match Columns( :Gender = :Gender, :Ethnicity = :Ethnicity, :Age = :Age )
);
// Add the sample to the dtPool table
dtPool = dtPool << concatenate( dtTemp, append to first table( 1 ) );
// Delete the selected rows from the working table
dt2 = dt2 << Update( With( dtTemp ), Match Columns( :__row__ = :__row__ ) );
//
dt2 << select where( Is Missing( :Pool Number ) == 0 );
dt2 << delete rows;
dt2 << delete columns( :Pool Number );
// Cleanup temporary tables
Close( dtTemp, nosave );
Close( dtPoolCount, nosave );
);
If( N Rows( dt2 ) > 0,
// Calculate the new pool numbers
dtPoolCount = dt2 << Summary(
Group( :Gender, :Ethnicity, :Age ),
Freq( "None" ),
Weight( "None" ),
Link to original data table( 0 )
);
// Get the current pool number
maxPool = Col Max( dtPool:Pool Number );
If( Is Missing( maxPool ),
maxPool = 0
);
// Add Pool Number to Pool Count table
dtPoolCount << New Column( "Pool Number", set each value( maxPool + Row() ) );
dtPoolCount << delete columns( N Rows );
// Set the current pool number in the current sample table
dt2 = dt2 << Update(
With( dtPoolCount ),
Match Columns( :Gender = :Gender, :Ethnicity = :Ethnicity, :Age = :Age )
);
// Add the sample to the dtPool table
dtPool = dtPool << concatenate( dt2, append to first table( 1 ) );
// Clean up
Close( dtPoolCount, nosave );
);
// Add the Pool Number to the original data table
dt << Update( With( dtPool ), Match Columns( :__Row__ = :__Row__ ) );
// Delete the Working data table and the Pool Count data table
Close( dt2, nosave );
Close( dtPool, nosave );