데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.최근 커뮤니티 토론 Re: 전체 테이블에서 숫자 값을 찾아 누락된 값으로 바꾸는 스크립트 에서 제공한 아주 좋은 항목이 있었습니다. @SDF1 솔루션으로 선택한
names default to here(1);
dt=current data table();
For( i = 1, i <= N Rows( dt ), i++,
For( l = 1, l <= N Cols( dt ), l++,
If( Column( l )[i] == 999,
Column( l )[i] = .
)
)
);
솔루션을 보았을 때 "데이터 테이블을 반복하지 마십시오.루핑이 느립니다. JMP 내장 기능 사용"
그래서 수정을 시작했습니다 @SDF1 암호.
"Get Rows Where()"의 대체 표준이 더 빠를 것이라고 결정했습니다.결국, "매우 빠른" Get Rows Where()가 행을 찾은 후 발견된 모든 행을 하나의 할당문으로 설정할 수 있습니다.
내가 본 또 다른 솔루션 밀린 커뮤니티에서 권장하는 것은 JMP의 Recode 기능입니다.
그래서:
가설: Get Rows Where 및 Recode의 JMP 함수에서 빌드는 전체 데이터 테이블에 걸쳐 루프 다운보다 빠를 것입니다.
반도체 능력 데이터 테이블을 적당한 크기의 테이블로 선택했는데, 132열 1455행
각 열에 10개의 임의 값을 999로 설정하는 작은 스크립트를 작성했습니다.
names default to here(1);
dt=current data table();
for(i=5,i<=ncols(dt),i++,
if(col stddev(ascolumn(dt,i))!=0,
for(k=1,k<=10,k++,
column(dt,i)[randominteger(1,1455)]=999;
)
));
이것은 위에서 언급한 토론에서 변경될 원래 값입니다.999는 스크립트에 의해 누락(.)으로 변경됩니다.
방법:
- JMP 16 시작.
- 반도체 능력 데이터 표 읽기
- 스크립트를 실행하여 각 열에 999개의 값을 설정합니다.
- 3가지 방법 각각에 대해 위의 2단계를 반복하고 시간을 밀리초로 다시 코딩합니다.
- JMP15에 대해 위의 단계를 반복합니다.
다음은 Recode용 스크립트입니다.
Names Default To Here( 1 );
dt = Current Data Table();
start = HP Time();
For( i = 5, i <= N Cols( dt ), i++,
dt << Recode Column(
As Column( dt, i ),
{If( _rcNow == 999, ., _rcNow )},
Target Column( As Column( dt, i ) )
)
);
show(hptime()-start)
Get Rows Where 코드
names default to here(1);
dt=current data table();
start=hptime();
for(i=5,i<= ncols(dt),i++,
column(dt,i)[dt<<GET rows="" where=""></GET>
그리고 여기 놀라운 결과

For 루프가 승리합니다.그리고 결과에서 Get Rows Where는 드물게 사용해야 합니다.
댓글과 수정 환영합니다.......
데이터 테이블스크립팅Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.네 이해했습니다 @brady_brady . 그러나 다음과 같이 할 수 있습니다.
NamesDefaultToHere(1);
// Make an example table with some rogue '999' values
nr = 10; // Number of rows
nc = 10; // Number of columns
p = 0.1; // Fraction of rogue values
val = 999; // Rogue value
m = J(nr, nc, RandomInteger(1, 10));
m = Shape(m, nr*nc, 1);
m[RandomIndex(nr*nc, Floor(nr*nc*p))] = val;
m = Shape(m, nr, nc);
dt = AsTable(m);
dt << setName("Rogue Values");
Wait(3);
// Set rogue values to '.'
mask = J(nr*nc, 1, 1);
mask[Loc(dt[0,0] == val)] = .;
mask = Shape(mask, nr, nc);
dt[0,0] = mask :*</img> dt[0,0];
그러나 나는 이것이 요소 현명한 곱셈 때문에 이미 가지고 있는 것보다 더 빠를지 매우 의심스럽습니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.여기에서 비교가 약간 잘못되었습니다. "Get Rows Where" 기능은 각 행에서 해당 표현식을 평가하므로 루프를 실행하기 전에 불필요한 조회를 최소화해야 합니다. 특히 반복자는 외부에 있고 각 행에서 찾기 위해 스코프 워킹을 해야 합니다.또한 각 행에서 AsColumn 함수를 평가하여 매번 'dt'와 'i'를 모두 조회합니다.이것은 _매우_ 비쌉니다.이에 대한 적절한 방법은 다음과 같습니다.
names default to here(1);
dt=current data table();
start=hptime();
names = dt << Get Column Names( "string" );
for(i=5,i<= ncols(dt),i++,
Eval( Parse( Eval InserT( JSL Quote(
column(dt,i)[dt<<GET rows="" where=""></GET>
이것이 3000배 더 빠르게 실행된다는 것을 알 수 있습니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.예... 문제는 행렬이 단일 인덱스(행 중심 레이아웃을 가정함)로 액세스할 수 있지만 데이터 테이블은 액세스할 수 없다는 것입니다. 따라서 슬프게도 아날로그가 없습니다.
m[loc(m, 9999)] = .
여기서 m은 데이터 테이블 세계에서 pxq 행렬입니다... 따라서 위의 코드에서 이 행의 앞뒤에 있는 행입니다. 코드는 여전히 빠르지만 테이블에 단일 인덱스 액세스를 사용할 수 있다면 정말 빠를 것입니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.'를 위해 행렬을 만드는 데 드는 오버헤드' 데이터 테이블 첨자 도움이 될 수 있습니다.@Craige_Hales 알 것이다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.행렬을 만들고 나중에 테이블에 다시 할당하는 데 오버헤드가 있지만 루핑을 방지하는 방법이 있습니다. 이 접근 방식은 이 데이터에 대해 loc_2d와 거의 동일하게 빠르게 수행되지만 테이블이 커질수록 상대적 성능이 저하될 것으로 예상하지만 이를 확인하지는 않았습니다.
expr_mat = expr(
m = dt[0, 5 :: N Col( dt )];
m[Loc( m, 999 )] = .;
dt[0, 5 :: N Col( dt )] = m;
);
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.아마도 이것에 대해 너무 깊숙이 들어갔을 것입니다(그러나 내가 해야 하는 경우 나중에 이러한 유형의 테스트를 수행하는 방법에 대한 일종의 아이디어를 얻었습니다).
나는 999를 누락된 것으로 대체하는 다양한 방법을 테스트하기 위해 다른 표현식으로 일종의 테스트 스크립트를 작성했습니다. 두 개의 데이터 세트(Semiconductor Capability.jmp 및 Probe.jmp)로 테스트하고 열에서 누락된 값의 양을 변경했습니다.
Loc()은 값을 교체하는 데 가장 빠릅니다(놀랍지 않습니다). Missing Value Codes()는 "항상" 빠르지만 Loc()과 비교할 때 사용 사례가 조금 더 제한적이며 대체할 값이 여러 개인 경우 사용하는 것이 좀 더 번거롭습니다.

가장 빠른 것은 loc_2d가 되었습니다(다음에서 변수 이름을 변경하는 것을 귀찮게 하지 않았습니다. 2D 행렬과 함께 Loc 사용하기 ). (적어도 내가 아는 한) 값을 설정하려면 계속 반복해야 하므로 이것이 Loc()보다 빠른 이유는 일부 열을 건너뛰기 때문일 가능성이 큽니다. 다음은 expr_loc2d 및 expr_loc입니다.
expr_loc = Expr(
for(i=5,i<= ncols(testData),i++,
column(testData,i)[Loc(testData[0,i], 999)]=.;
);
);
expr_loc_2d = Expr(
mat = testData[0,5::NCols(testData)];
nr = N Rows(mat);
nc = N Cols(mat);
blacklocs = Loc(mat, 999) - 1;
rowlocs = Floor((blacklocs) / nc ) + 1;
collocs = Mod((blacklocs), nc ) + 1 + 4;
uniqCols = Associative Array(collocs) << get keys;
For(i_2d = 1, i_2d <= N Items(uniqCols), i_2d++,
testData[rowlocs[Loc(collocs, uniqCols[i_2d])], uniqCols[i_2d]] = .;
);
);
또한 AsColumn(Column(dt, i)) 다음과 같이 사용하는 것이 중요한 것 같습니다. @Ryan_Gilmore (매우 느릴 것이기 때문에 << get rows where it 없이는 테스트를 귀찮게하지도 않았습니다), 그러나 Column()이 있거나 없는 테스트 레코딩을 수행했습니다. 또한 recode에서 하나의 Column()을 놓쳤으므로 몇 가지 빠른 테스트를 실행하십시오(데이터 또는 스크립트에 첨부되지 않음).
이 세 가지의 상당히 큰 차이:
expr_recode_ascolumn = Expr(
For(i = 5, i <= N Cols(testData), i++,
testData << Recode Column(
As Column(dt, i),
{If( _rcNow == 999, ., _rcNow)},
Target Column(As Column(testData, i))
)
);
);
expr_recode_ascolumn_column = Expr(
For(i = 5, i <= N Cols(testData), i++,
testData << Recode Column(
As Column(dt, i),
{If( _rcNow == 999, ., _rcNow)},
Target Column(As Column(Column(testData, i)))
)
);
);<BR />
expr_recode_ascolumn_column_column = Expr(
For(i = 5, i <= N Cols(testData), i++,
testData << Recode Column(
As Column(Column(dt, i)),
{If( _rcNow == 999, ., _rcNow)},
Target Column(As Column(Column(testData, i)))
)
);
);

테스트 스크립트 및 일부 결과 데이터가 첨부되었습니다. 스크립트는 여기 저기에 약간의 실수가 있을 가능성이 높습니다. 누군가가 원하는 경우 새로운 표현을 추가하는 것이 상당히 쉬워야 합니다. 내가 전혀 테스트하지 않은 한 가지는 << 시작/종료 데이터 업데이트를 사용하는 것입니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.흥미로운 토론! JMP 13에서 처음 등장한 데이터 테이블 행렬 표기법은 할당에 매우 효율적입니다.
이 특정 문제의 경우 for 루프(0,003 대 1.5초, JMP 15 Mac 노트북)보다 거의 500배 빠릅니다.
start = HP Time();
For( i = 5, i <= N Cols( dt ), i++,
Try( dt[Loc( dt[0, i], 999 ), i] = . )
);
Show( HP Time() - start);
"999"가 없는 열에 대한 오류를 방지하려면 try()가 필요합니다.
전체 행렬에 대한 직접 할당이 작동하지 않기 때문에 열에 대한 루핑이 여전히 필요합니다. 오류: "여러 첨자는 액세스 또는 평가의 각 내부 수준에서 단일 첨자가 필요합니다...", 두 번째 생각에 의미가 있습니다.
// The left Data Table matrix syntax is OK on its own, but not for assignment.
dt[0, 5 :: N Col( dt )][Loc( dt[0, 5 :: N Col( dt )], 999 )] = .;
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.나는 어느 시점에서 루프를 사용하는 것을 경계했을 수도 있지만 하나의 알고리즘 코스(나는 끝내지 않은 ..)를 수강한 후에는 조금 덜했습니다. 당신은 그것들을 효율적으로 사용해야 하고, 꽤 자주 너무 많이 반복합니다(시간 복잡도와 Big O 표기법). 또한 루프를 사용하는 것은 순수한 수학으로 문제를 해결하는 것보다 훨씬 쉽습니다.
JMP를 사용하면 속도가 거의 문제가 되지 않기 때문에 보통 어느 시점에서 배운 안전한 옵션을 사용합니다. 그러나 시간이 문제일 때(하나의 응용 프로그램이 직장에서 여는 데 6분이 넘게 걸렸음) 더 빠르게 만드는 방법을 찾기 시작할 것입니다(2분 이내에 시작되도록 관리). 이 경우 다른 기능(행 삭제, 행 상태 설정)의 다른 조합과 함께 Loc()을 사용하여 더 빠르게 만들 수 있었습니다.
Loc() 외에도 Summarize()를 사용하면 열에서 고유한 값을 가져오는 데 내가 오랫동안 즐겨 사용하는 옵션(associative array() << get keys)과 비교할 때 "방법"이 더 빠른 것 같습니다. 행 수가 증가하면 Associative array() << get keys가 점점 느려지고 Summarize()는 적어도 빠르지는 않지만 동일한 문제를 겪지 않는 것 같습니다. 그래서 Summarize()를 더 많이 사용하려고 시도했습니다(데이터 테이블의 높이가 얼마나 되는지 알 수 없음).
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.그래서 우리는 AsColumn()을 다음과 같이 건너뜁니다.
start=hptime();
for(i=5,i<= ncols(dt),i++,
column(dt,i)[Loc(dt[0,i], 999)]=.;
if(mod(i,10)==0,show(i));
);
show(hptime()-start);
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.Loc()이 가장 좋은 방법이라는 데 동의합니다.
저에게는 As Column 때문에 느려지는 것 같습니다. 나는 사이에 상당한 차이를 본다,
start = HP Time();
For( i = 5, i <= N Cols( dt ), i++,
As Column( column(dt, i) );
);
Show( HP Time() - start );
그리고
start = HP Time();
For( i = 5, i <= N Cols( dt ), i++,
As Column( dt, i );
);
Show( HP Time() - start );
코드에서 As Column 구문 변경 @txnelson 원래 질문은 For 루프가 여전히 가장 빠르지만 다른 루프는 더 비슷합니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.안녕 @txnelson ,
매우 흥미로운 비교이며 내가 기대했던 결과도 아닙니다. 내가 대학에서 처음 프로그래밍을 배우기 시작했을 때 비슷한 내용을 배웠던 때가 기억납니다. 루프는 느리기 때문에 조심하십시오.
확실히, 일부 계산과 일부 프로그램에서 For 루프가 대안보다 매우 느립니다. 나는 프로그래머가 그다지 뛰어나지 않기 때문에 내가 할 줄 아는 것에 의존하는 경향이 있습니다. 이것이 항상 빠르거나 우아하지는 않습니다. 때로는 루프의 논리를 통해 내가 원하는 작업을 수행할 수 있는 기능 코드를 작성할 수 있으므로 다음 단계로 넘어갈 수 있습니다.
For Loop 및 Recode 옵션이 JMP 16과 15에서 약간 느리지만 Get Rows Where가 시간을 거의 절반으로 줄임으로써 개선되었다는 것은 상당한 변화입니다.
감사!,
DS
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.아마도 @Craige_Hales 더 빠른 솔루션을 제공할 수 있습니다. 나는 그의 커뮤니티 게시물/블로그에서 Matrix 계산(특히 Loc())을 사용하는 아이디어를 얻었습니다.
데이터 세트를 연 다음 (사용자 선택에 따라) 오래된 데이터를 삭제하는 하나의 도구를 더 빠르게 만들었습니다. 원래 << Select Where 및 Delete rows를 사용했습니다. 나는 그것을 일부 Loc() 마법으로 대체했고 훨씬 더 빨라졌습니다. 나는 최근에 Loc()을 정말 좋아했습니다.
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.@jthi ,
매트릭스 기반 코드가 가장 빠른 것으로 나타났습니다.
0.299795초.......
Re: 데이터 테이블을 반복하거나 Recode를 사용하거나 Get Rows Where를 사용하여 데이터 테이블의 값을 변경해야 합니다.나는 우리가 가지고 있는 몇몇 오래된 스크립트에 대해 작업에서 약간의 최적화를 하고 있습니다. 내가 변경해야 했던 것들 중 일부는 행을 얻는 것과 관련이 있습니다. 빠른 JSL 코드가 필요한 경우 점점 더 많은 행렬 연산(대부분 Loc())을 사용하기 시작했습니다.
예를 들어 다음 위치에서 행 가져오기를 변경할 수 있습니다(올바른 값 또는 모든 값을 대체하는지 테스트하지 않음).
start=hptime();
for(i=5,i<= ncols(dt),i++,
column(dt,i)[Loc(ascolumn(dt,i) << get as matrix, 999)]=.;
if(mod(i,10)==0,show(i));
);
show(hptime()-start);
경우에 따라 작동할 수 있는 열 속성 값 레이블 및 누락된 값 코드를 사용하는 옵션도 있습니다. 가능하면 사용하는 것이 좋습니다. 그러면 데이터가 변경되지 않기 때문입니다.