무작위로 그룹으로 하위 선택하고 평균 얻기안녕,
3가지 범주(성별/연령/민족)로 계층화된 ~2000명의 개인 데이터 세트가 있습니다. 각 성별/연령/민족에서 ~ 8명의 개인을 선택하고 평균을 찾아 이러한 개인에 대한 값을 "통합"하고 싶습니다. 주의할 점은 특정 범주 빈에 다른 사람보다 더 많은 개인이 있다는 것입니다. 내가 얻은 모든 개인과 그들의 그룹에 대한 분석이 첨부되어 있습니다. 예를 들어 카테고리 1-1-1에는 120명의 개인이 있으므로 이들로부터 8*15개의 무작위 개인 그룹을 만들 수 있습니다. 8의 배수가 아닌 숫자가 있으면 어떻게 합니까?
이 모든 작업을 한 번에 수행하려면 어떻게 해야 합니까? 결국 우리는 약 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: 무작위로 그룹으로 하위 선택하고 평균을 얻습니다.
안녕하세요 짐,
이 스크립트는 빈 테이블을 생성합니다. 여기서 얻고자 하는 것은 "Pool Number"라는 원래 데이터 테이블의 새 열입니다. 한 가지 주의할 점은 나이는 연속적인 숫자 변수가 아니라는 것입니다. 숫자 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 );