ランダムにグループにサブ選択し、平均を取得しますやあ、
私は、3つのカテゴリ(性別/年齢/民族)で階層化された約2000人の個人のデータセットを持っています。 私は、各性別/年齢/民族から最大8人の個人を取得し、平均を見つけることによって、これらの個人の「プールされた」値を取得したいと考えています。 注意点は、特定のカテゴリのビンには他のカテゴリよりも多くの個人がいることです。 添付されているのは、私が取得したすべての個人とそのグループの内訳です。 たとえば、カテゴリ1-1-1には120人の個人がいるので、これらからランダムな個人の8*15グループを作成できます。 8の倍数ではない数がある場合はどうなりますか?
どうすればこれをすべて1つのステップで実行できますか? 最終的には約200のプールができます。

スクリプティングRe:ランダムにグループにサブセレクトして平均を得る私はあなたが望むことをするスクリプトを作成したかどうかは完全にはわかりませんが、それはあなたに良いスタートを与えるかもしれません。これが何をするかです
- 人口が最も少ない性別/年齢/民族グループを検索します。このグループは、複数のプールに行を表示できないため、作成できるプールの数を制限します。
- 次に、そのサブグループに含まれていない行の数を最小化するプールサイズを見つけようとします。これは、グループサイズを8から21まで増やすことによって行われ、最小の余り(無駄)を見つけます。
- 次に、元のテーブルから作業テーブルを作成します。
- 作業テーブルをループし、
- 層化ランダムサンプルを作成します
- 新しいサンプルを最終的なプールデータテーブルに追加します
- 作業データテーブルから、最新のサブセット化されたランダムデータテーブル用に選択された行を削除します。
- 可能な限り多くの最小サブグループレコードを最終的なプールされたデータテーブルに取得するために、可能な限り繰り返します。
これが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 );
作成したサンプルデータテーブルでこれをテストしたため、実際のテーブルで問題が発生する可能性があります。コードに注釈を付けたので、私が行ったことを学習し、必要に応じて正確に機能するように調整できることを願っています。
Re:ランダムにグループにサブセレクトして平均を得る
こんにちはジム、
このスクリプトにより、テーブルが空白になります。 これから抜け出したいと思っているのは、元のデータテーブルの「プール番号」という新しい列です。 注意すべきことの1つは、年齢は連続数値変数ではないということです。 これは、数値1〜4の間のカテゴリ変数です。
元のデータセット内のすべてのサンプルをプール内に分類したら、プール内の最大8つのサンプルの平均をとることで平均プール値を計算できます。
参考までにファイルを添付しました。
作業テーブルはスクリプトで意味があります。各行が一意の値を持つ列を作成しています。 最終的なデータセットを作成すると、空白のデータシートが作成され、このエラーがどこから発生しているのかわかりません。
Re:ランダムにグループにサブセレクトして平均を得る潜在的なプールサイズが6に減少すると、JSLは正常に完了します。私のコードでは、各サブグループから少なくとも1つのサンプルを取得できる必要があります。サブグループなので、1 2 4には6つの観測値(行)しかありません。最適なサンプルサイズを見つけるために作成したコードは、プールサイズが6になるように変更する必要がありました。
しかし、それにもかかわらず、私はあなたがあなたのプールをどのように決定しているのか理解していないようです。私はあなたのプールを、データのサブグループごとに、与えられたサンプルサイズのランダムなサンプルと同一視していました。これは私の側の誤った仮定であることが判明しました。
サブグループごとに独立してプールを作成していますか?つまり、サブグループ1 1 1の場合、120行のデータがあります。プールサイズが8の場合、15個のプールを作成しますか?次に、50行のグループ1 1 2の場合、6つのプールを作成し、4つの行がプールに選択されていませんか?
これはあなたがあなたのプールを作る方法ですか?
これは、すべての性別/民族/年齢のサブグループの内訳です。

私の現在のJSLはあなたが望むことをしていません。プールを作成する方法のより正確な説明を教えてください。そして、実行可能なスクリプトをまとめるために何をする必要があるかを見ていきます。
Re:ランダムにグループにサブセレクトして平均を得るこんにちはジム、
サブグループは、各プールに最大8人の個人がいることによって作成されます。 あなたは1-1-1に関して正しいです。 このグループには120人の個人がいるため、これらの個人をランダムにプールする場合は、正確に15個のプールに収まる必要があります。 50行のグループ1-1-2の場合、8人の個人からなる6つのプールを作成し、残りの4つを独自のプールに入れます。
それは理にかなっていますか? データテーブルのすべての行を特定のプール番号に関連付ける必要があります。
Re:ランダムにグループにサブセレクトして平均を得る以下は、サンプルデータテーブルで機能し、必要なすべてのプールを作成するスクリプトです。時間をかけてスクリプトを調べて、最終的な形式に調整するために必要な変更を加えることができるようにしてください。
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 );