Seleziona casualmente in gruppi e diventa cattivoCiao,
Ho un set di dati di circa 2000 individui stratificati per 3 categorie (genere/età/etnia). Voglio ottenere valori "raggruppati" per questi individui prendendo circa 8 individui di ogni genere/età/etnia e trovando la media. Un avvertimento è che ci sono più individui in determinati contenitori di categoria rispetto agli altri. In allegato è una ripartizione di tutte le persone che ho avuto e il loro raggruppamento. Ad esempio, la categoria 1-1-1 ha 120 individui, quindi potrei creare 8*15 gruppi di individui casuali da questi. Cosa succede se ho un numero non multiplo di 8?
Come posso fare tutto questo in un solo passaggio? Alla fine avremmo circa 200 piscine.

SceneggiaturaRe: Sottoseleziona casualmente in gruppi e diventa cattivoNon sono del tutto sicuro di aver creato uno script che fa quello che vuoi, ma potrebbe darti un buon inizio.Ecco cosa fa
- Trova il gruppo di genere/età/etnia che ha la popolazione più piccola.Questo gruppo sarà il limitatore del numero di pool che possono essere creati poiché nessuna riga può apparire in più di un pool.
- Quindi tenta di trovare la dimensione del pool che ha ridotto al minimo il numero di righe non incluse per quel sottogruppo.Lo fa salendo la dimensione del gruppo da 8 a 21, e trova il più piccolo resto (rifiuti).
- Quindi crea una tabella di lavoro dalla tabella originale.
- Scorre il tavolo di lavoro,
- Crea un campione casuale stratificato
- Aggiunge il nuovo campione alla tabella dei dati del pool finale
- Elimina dalla tabella di dati di lavoro le righe selezionate per l'ultima tabella di dati casuali con sottoinsiemi.
- Si ripete il maggior numero di volte possibile per ottenere il maggior numero possibile di record di sottogruppi più piccoli nella tabella di dati in pool finale.
Ecco il 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 );
L'ho testato su una tabella di dati di esempio che ho creato, quindi potrebbe avere alcuni problemi con la tabella effettiva.Ho annotato il codice, quindi spero che tu possa imparare cosa ho fatto e essere in grado di apportare modifiche per farlo funzionare esattamente come ti serve.
Re: Sottoseleziona casualmente in gruppi e diventa cattivo
Ciao Jim,
Questo script genera una tabella vuota. Quello che spero di ottenere da questo è una nuova colonna nella tabella di dati originale chiamata "Numero pool". Una cosa da notare è che l'età non è una variabile numerica continua. È una variabile categoriale tra i numeri 1 - 4.
Una volta che ho tutti i campioni nel set di dati originale classificati all'interno del loro pool, posso calcolare il valore medio del pool prendendo la media dei ~8 campioni nel pool.
Ho allegato il file come riferimento.
Il tavolo di lavoro ha senso nella sceneggiatura; stai creando una colonna con ogni riga con un valore univoco. La creazione del set di dati finale porta a un foglio dati vuoto e non vedo da dove derivi questo errore.
Re: Sottoseleziona casualmente in gruppi e diventa cattivoIl mio JSL viene completato correttamente se la dimensione potenziale del pool viene ridotta a 6. Il mio codice richiede che almeno 1 campione deve essere in grado di essere estratto da ciascun sottogruppo e, poiché il sottogruppo, 1 2 4 ha solo 6 osservazioni (righe), il il codice che ho scritto per trovare la dimensione del campione migliore doveva essere modificato per avere una dimensione del pool di 6.
Ma a prescindere da ciò, a quanto pare non capisco come stai determinando i tuoi pool.Stavo identificando il tuo pool, a un campione casuale, con una determinata dimensione del campione, per ogni sottogruppo di dati.Questo risulta essere un falso presupposto da parte mia.
Stai creando pool in modo indipendente per ogni sottogruppo?Cioè, per il sottogruppo 1 1 1, ci sono 120 righe di dati.Se la dimensione del pool è 8, crei 15 pool?E poi per il gruppo 1 1 2 che ha 50 righe, creeresti 6 pool, con 4 righe non selezionate per un pool?
È così che crei le tue piscine?
Ecco la ripartizione di tutti i sottogruppi di genere/etnia/età.

Il mio attuale JSL non fa quello che vuoi, per favore dammi una spiegazione più precisa su come creare pool e vedrò cosa è necessario fare per mettere insieme uno script funzionante.
Re: Sottoseleziona casualmente in gruppi e diventa cattivoCiao Jim,
I sottogruppi vengono creati avendo ~ 8 individui in ogni pool. Hai ragione per quanto riguarda 1-1-1. Questo gruppo ha 120 individui, quindi se dovessimo raggruppare questi individui in modo casuale dovrebbero rientrare esattamente in 15 pool. Per il gruppo 1-1-2, che ha 50 righe, creeresti 6 pool di 8 individui e i restanti 4 verrebbero inseriti nel proprio pool.
Ha senso? Vogliamo che tutte le righe nella tabella di dati siano associate a un numero di pool specifico.
Re: Sottoseleziona casualmente in gruppi e diventa cattivoDi seguito è riportato uno script che funziona sulla tabella di dati di esempio, creando tutti i pool desiderati.Ti preghiamo di dedicare del tempo a studiare lo script in modo da poter apportare tutte le modifiche necessarie per adattarlo alla sua forma finale
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 );