隨機分組並取得平均值你好,
我有一個大約 2000 人的資料集,以 3 個類別(性別/年齡/種族)進行分層。 我想透過從每個性別/年齡/種族中選取約 8 個人並找出平均值來「匯總」這些人的值。 需要注意的是,某些類別箱中的個體比其他類別箱中的個體更多。 附件是我得到的所有個人及其分組的詳細資訊。 例如,類別 1-1-1 有 120 個個體,因此我可以從中創建 8*15 組隨機個體。 如果我的數字不是 8 的倍數怎麼辦?
我怎樣才能一步完成這一切? 最終我們會有大約 200 個池。

資料混合與清理回覆:隨機分組並取得平均值以下是一個適用於範例資料表的腳本,可建立您想要的所有池。請花時間研究腳本,以便您可以進行任何可能需要的修改,將其調整為最終形式
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 );回覆:隨機分組並取得平均值嗨吉姆,
每個池中約有 8 個人即可建立子群組。 關於 1-1-1,您是正確的。 該組有 120 個人,因此如果我們將這些人隨機匯集在一起,他們應該正好適合 15 個池。 對於具有 50 行的群組 1-1-2,您將建立 6 個由 8 個人組成的池,其餘 4 個將放入自己的池中。
那有意義嗎? 我們希望資料表中的所有行都與特定的池號相關聯。
回覆:隨機分組並取得平均值如果潛在池大小減少到 6,我的 JSL 將成功完成。我的程式碼要求必須能夠從每個子組中提取至少 1 個樣本,並且由於子組 1 2 4 僅具有 6 個觀察值(行),因此我為找到最佳樣本大小而編寫的程式碼必須修改為池大小為6。
但無論如何,我顯然不明白你是如何確定你的池的。對於每個資料子組,我將您的池等同於具有給定樣本大小的隨機樣本。事實證明,這對我來說是一個錯誤的假設。
您是否為每個子組獨立建立池?也就是說,對於子組 1 1 1,有 120 行資料。如果池大小為 8,您是否建立 15 個池?然後,對於具有 50 行的群組 1 1 2,您將建立 6 個池,而沒有為池選擇 4 行?
這就是你創建池的方式嗎?
以下是所有性別/種族/年齡分組的細分。

我目前的 JSL 沒有達到您想要的效果,請給我一個關於如何創建池的更精確的解釋,我將了解需要做什麼才能組合出一個可行的腳本。
回覆:隨機分組並取得平均值
嗨吉姆,
該腳本會產生一個空白表。 我希望從中得到的是原始資料表中的一個新列,稱為「池號」。 需要注意的一件事是年齡不是連續數值變數。 它是數字 1 - 4 之間的分類變數。
一旦我將原始資料集中的所有樣本分類到池中,我就可以透過池中 ~8 個樣本的平均值來計算平均池值。
我已附上該文件作為參考。
工作表在腳本中有意義;您正在建立一列,每一行都有一個唯一的值。 最終資料集的建立會導致資料表空白,我不知道這個錯誤是從哪裡產生的。
回覆:隨機分組並取得平均值我不完全確定我已經創建了一個可以實現您想要的功能的腳本,但它可能會給您一個良好的開端。這是它的作用
- 它找到人口最少的性別/年齡/種族群體。這一組將限制可以建立的池數量,因為任何行都不能出現在多個池中。
- 然後,它嘗試找到使該子組的未包含行數最小化的池大小。它透過將群組大小從 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 );
我在我創建的範例資料表上對此進行了測試,因此它可能與您的實際表存在一些問題。我已經對程式碼進行了註釋,因此希望您能夠了解我所做的事情,並能夠進行調整以使其完全按照您的需求工作。