정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시합니다.다음을 수행하는 JSL 스크립트를 찾고 있습니다.
-
활성 데이터 테이블에서 현재 선택된 열을 가져옵니다.
-
첫 번째로 선택된 열을 가져옵니다.
-
사용자에게 정규 표현식을 입력하라는 메시지를 표시합니다.
-
해당 열의 값이 정규식과 일치하는 테이블의 행만 선택합니다.
-
일치하는 행만 표시하는 데이터 보기 창을 엽니다.
이것이 JSL로 가능할까요?
자동화 및 스크립팅데이터 액세스Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시가능합니다. 어떤 방법을 시도해 보셨나요?
이것은 구현될 수 있는 (그리고 아마도 구현되어야 하는) 모든 검사를 누락한 매우 기본적인 예입니다.
Names Default To Here(1);
dt = Current Data Table();
col = (dt << Get Selected Columns("String"))[1]; // I suggest dropping non-character columns
run_expr = Expr(
rgx_pattern = teb << Get Text; // You could check if the pattern is valid regex
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
// add check if any rows have been selected
dt << Data View; // If linked subset is fine, that is most likely better as it can avoid using select where
dt << Clear Select;
wait(0);
);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("")
),
Lineup Box(N Col(1),
Button Box("OK",
run_expr
),
Button Box("Cancel")
)
)
);
Write();
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시고맙습니다. 잘 되네요.
솔직히 말해서 제가 시도한 것이 실제와 크게 다르지 않아서 코드를 하나도 넣지 않았고, 아마도 AppleScript와 Matlab에서 GUI 스크립팅을 배우면서 생긴 JSL에 대한 근본적인 오해가 드러날 것입니다.
선택한 열 이름 목록을 가져와서 첫 번째 열 이름을 선택하려고 했는데, 문자열을 반환하는 "대화 상자 표시" 함수가 있을 줄 알았는데, 그런 함수가 없는 것 같아서 새 창/목록 상자/버튼 표현식 구문을 사용해야 합니다. 제겐 다소 직관적이지 않았지만, 이제 무슨 기능인지 알게 되어서 더 이해가 됩니다. ChatGPT를 사용해 봤는데, 전혀 실행되지 않는 긴 스크립트가 생성되었습니다.
시간이 있으시다면 귀하의 솔루션에 대한 몇 가지 질문을 드리겠습니다.
- "취소" 버튼이 왜 작동하지 않나요? Button Box() 호출에 두 번째 인수가 없어서 그런 것 같습니다. 그런데 현재 창을 닫는 표현식은 무엇인가요? Close()인가요? "Button Box ( "취소" , 닫다 ())"를 시도해 봤는데, 이해할 수 없는 오류가 발생해서 오류가 발생합니다. 작성하신 방법을 따라 "창 닫기"를 시도해 봤는데, 잘 작동하는 것 같지만, 더 깔끔한 방법이 있을 것 같습니다.
- "Get Selected Columns()" 호출에 "문자열"이 인수로 포함되어 있는데, 설명서에는 해당 함수가 인수를 받지 않는다고 나와 있습니다. 여기서 "문자열"은 무엇을 의미하며, 이 문자열이 받아들여질지, 또는 어떤 역할을 하는지 어떻게 아셨나요?
- 스크립트를 실행하자마자 바로 입력을 시작하고 싶은데, 포커스가 올바른 위치에 없습니다. "nw=..." 표현식 뒤에 "teb << SetFocus;"를 입력해 보았지만, JMP에서 텍스트 편집 상자가 해당 메시지를 인식하지 못한다고 합니다.
- 정규 표현식을 대소문자를 구분하지 않게 할 수 있나요? 가능하다면 어떻게 해야 하나요? (" "문서에 따르면 정규식 인수에 "를 입력했지만 오류가 발생합니다.)
- teb 상자에 초점을 맞춘 상태에서 return/enter 트리거로 "Ok" 스크립트를 실행할 수 있을까요?
- 사용자가 선택한 열이 없으면 첫 번째 문자 열을 사용하고 싶지만, 약 20번 시도한 후 어떤 열인지 알아내려고 노력하다가 포기했습니다.
- 데이터 뷰 하위 집합을 연결하는 것을 선호하는데, 그렇게 하면 접근 방식이 바뀌나요?
지금까지 제가 알고 있는 내용은 다음과 같습니다.
Names Default To Here(1);
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns("String");
if(N Items(selCols)==0, selCols = dt << get column names("String") );
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt << Data View; // I prefer a linked subset, what changes here?
dt << Clear Select;
wait(0);
nw << Close Window;
);
close_expr = Expr(nw << Close Window);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("", <
<SET width=""></SET>
<P>Big Class를 열고 스크립트를 실행한 다음 "ob.+t"를 입력하고 싶습니다.<ENTER> "라고 말하고, 두 로버츠만 있는 데이터 뷰를 불러오도록 했습니다. 지금은 거의 다 됐어요. 스크립트를 실행한 후 Tab 키를 누르고, OB.+T 키를 누르고, Enter 키를 두 번 눌러야 해요.</ENTER></P>
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시- 가능한 한 최소한의 예를 만들었으므로 Cancel에는 창을 닫는 표현식이 포함되지 않습니다.
- 방금 "문자열"이 << get column names()처럼 작동하는지 확인해 봤는데, 잘 작동합니다. "문자열" 값 없이 테스트해 보고 어떤 결과가 나오는지 확인해 보세요(문자열 대신 참조). 제 생각에는 열 참조를 다루는 건 정말 골치 아픈 일이라 항상 열 이름 문자열을 사용하고 필요에 따라 변환합니다. 하지만 참조(혹은 콜론 구문)를 사용할지는 전적으로 사용자의 선택입니다.
- 복잡한 해결 방법을 사용하지 않는 한 탭을 사용해야 할 것 같습니다 . 대화형 디스플레이 요소(TextEditBox, Button...)와 함께 SetFocus를 사용할 수 있도록 허용합니다.
- 사용자 입력을 Lowercase()로 처리하고 열 참조를 Lowercase()로 감쌀 수 있습니다. 또는 INGORECASE를 사용할 때 Regex()에 기본 캡처링 그룹을 추가할 수도 있습니다. 정규식("ABCD", "d", "\0", 대소문자 무시)
- 필요에 따라 << Set 함수를 사용해 보세요. 커밋 시 스크립트가 실행되고, Enter 키를 누르면 해당 스크립트가 실행됩니다(텍스트 편집 상자 밖을 클릭하는 경우에도 마찬가지입니다).
-
<< Get Column Names(Character, String)[1]
-
r = dt << Get Rows Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt_subset = dt << Subset(Rows(dt), Selected Columns(0), Link to original data table(1));
개선할 수 있는 부분은 많이 있지만, 어떤 것이 가능한지는 실제 사용 사례에 따라 달라집니다.
편집: 원본 데이터 테이블(1)에 대한 링크를 추가하여 하위 집합을 만들었습니다.
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시좋습니다. 감사합니다!
질문 하나만 더 드리겠습니다. 여러 열을 선택한 경우, 연결된 열 값에 대해 문자열로 정규식을 실행하고, 열이 선택되지 않은 경우 *모든* 열에 대해 동일한 작업을 수행하고 싶습니다. 이렇게 하면 테이블에서 egrep을 사용하는 것과 거의 동일한 동작을 합니다. 실제로 구현이 가능할까요? 제가 처음 시도했던 부분은 아래 주석 처리된 부분을 참고해 주세요. 하지만 선택된 열의 값만 가져오는 것이 아니기 때문에 아직 구현되지 않았습니다(그리고 작동하지도 않습니다).
Names Default To Here( 1 );
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns( "String" );
If( N Items( selCols ) == 0,
selCols = dt << Get Column Names( "String" )
);
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where( !Is Missing( Regex( Column( dt, col )[Row()], rgx_pattern, "1", IGNORECASE ) ) );
// dt << Select Where( !Is Missing( Regex( Concat Items( dt << get Rows(Row())," "), rgx_pattern, "1", IGNORECASE ) ) );
dt << Data View;
Wait( 0 );
);
close_expr = Expr( nw << Close Window; Wait( 0 ); );
nw = New Window( "Table Egrep",
H List Box(
lb1 = Lineup Box( N Col( 2 ),
Text Box( "Select column to Enter regex pattern" ),
teb = Text Edit Box( "", Set Script( run_expr ), <
<SET width=""></SET>
<P>참고로, 위의 "스크립트 설정"은 "Enter" 키 입력 시 즉시 실행되도록 처리하여 매우 잘 작동합니다. 원하는 동작 중 유일하게 빠진 부분은 위의 동작과 "Tab" 키를 눌러 텍스트 편집 상자로 포커스를 이동해야 하는 부분입니다.</P>
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시어느 시점에서 속도가 느려지기 시작할 수 있으며 문자 열만 선택되었는지 확인하는 검사를 추가해야 하지만 연결을 생성하기 위해 표현식을 빌드할 수 있습니다.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
dt << Select Columns({:name, :sex});
rgx_patter = "EF";
cols = dt << Get Selected Columns("String");
conc_expr = Expr(Concat());
For Each({colname}, cols,
Insert Into(conc_expr, Name Expr(As Column(dt, colname)));
);
regex_expr = Substitute(
Expr(!Is Missing(Regex(_conc_expr_, _rgx_pattern_, "\0", IGNORECASE))),
Expr(_conc_expr_), Name Expr(conc_expr),
Expr(_rgx_pattern_), rgx_pattern
);
rows_of_interest = dt << Get Rows Where(regex_expr);
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시모달 창을 사용하여 포커스가 창에 위치하도록 강제할 수도 있지만, 이는 사용자 경험에 매우 나쁜 영향을 미칠 수 있습니다.
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시내가 이해하기 시작했다고 생각했을 때...
설명서에는 Expr() 함수가 "인수를 평가되지 않은 상태로 반환한다"고 나와 있는데, 솔직히 저는 전혀 의미가 없습니다. 그냥 전달받은 대로 반환되는 것처럼 들리네요.
이전 코드에서는 서브루틴처럼 보였고, 당시에는 이해가 되었습니다. 그런데 지금 Expr(Concat())이 보이는데, 실제로 무엇이 연결되는지 알 수가 없습니다. 나중에 Expr() 객체를 Insert Into()로 연결했는데, JMP는 값을 어디에 삽입해야 할지 어떻게 알 수 있을까요? ChatGPT조차도 이 부분을 이해하는 데 도움이 되지 않습니다.
마치 마술사의 손동작만 따라하는 것처럼 느껴집니다. 특히 Get Row()에 대한 설명서에서는 제가 원하는 동작을 정확히 구현한다고 약속하고 있기 때문에 답답합니다.
물론, 이 모든 게 당신 잘못은 아니에요. 정말 도와주셔서 감사해요. 지금 제가 하는 일로도 충분히 잘 될 것 같아요. 감사합니다!
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시여기서는 아무것도 연결되지 않습니다. Expr(Concat())은 표현식 작성이 완료된 후 연결될 인수들을 수집하는 역할을 합니다. 표현식을 리스트로 작성한 후, 리스트를 concat으로 대체할 수도 있습니다.
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
val1 = "name";
val2 = "sex";
c = {};
Insert Into(c, Name Expr(As Column(dt, val1)));
Insert Into(c, Name Expr(As Column(dt, val2)));
show(c);
Substitute Into(c, Expr(List()), Expr(Concat()));
Show(c);
// Example use
Eval(EvalExpr(
dt << New Column("Concat", Character, Nominal, Formula(
Expr(Name Expr(c))
));
));
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시알겠습니다. 제가 이걸 알아낸 것 같습니다. 이 스크립트는 기본적으로 unix/linux/mac "egrep" 명령어의 표 형식 버전입니다. 즉, 사용자가 입력한 정규 표현식(검색 문자열)과 일치하는 행만 선택하거나 표시합니다.
Names Default To Here( 1 );
If(
ex = New Window( "Enter search regex",
<
<MODAL></MODAL>
<P>모든 버튼이 제대로 작동하고, 행이 수천 개라도 상당히 빠릅니다. 개인적으로는 이 기능을 추가해서 cmd-shift-e(egrep)에 연결해서 사용하고 있는데, 지금은 항상 사용하고 있습니다. 물론 개선 방안에 대한 제안도 환영합니다. 누군가에게 도움이 되기를 바랍니다!</P> <BR /> <P>(그리고 <A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A> 의 인내심과 통찰력에 큰 감사를 표합니다!)</P>
Re: 정규식과 일치하는 행의 하위 집합으로 데이터 보기를 빠르게 표시좋아 보이네요! 몇 가지 작은 변화를 주면 좋을 것 같아요.
- 새 창을 열기 전에 테이블이 열려 있는지 확인하고, 테이블이 없으면 stop()을 실행합니다.
- 일치하는 항목이 없으면 마지막 행에서 오류가 발생합니다. 선택된 행 개수를 확인하고 0이면 stop()을 사용하거나, 사용자에게 일치하는 항목이 없다는 정보를 표시할 수 있습니다.
- << 행 가져오기는 << 선택 위치보다 빠를 가능성이 높습니다.
- 열 참조를 평가하면 추가적인 속도 향상을 얻을 수 있습니다.
- << Validate는 첫 번째 정규식에 일치하는 것이 없는 경우 사용자가 새 정규식을 입력하도록 허용하려는 경우에도 사용할 수 있습니다.
더 보기...
Names Default To Here(1);
If(N Table() == 0,
stop(); // display error message to user if necessary
);
dt = Current Data Table();
nw = New Window("Enter search regex",
<
<MODAL>
0, col = selCols[1]; , col = Column(dt, 1) << get name; ); selrows = Eval(EvalExpr( dt << Get Rows Where(!Is Missing(Regex(Expr(NameExpr(As Column(dt, col))), inputRegex, "1", IGNORECASE))); )); If(N Rows(selrows) == 0, stop(); // display error message if necessary, this could also be done already within modal window (<< On Validate), if you wish to let user perform new search ); dt2 = dt << Subset(Rows(selrows), Selected Columns(0), Link to original data table(1), Output Table("")); // dt2 << Select Rows(1::NRows(dt2)); // to select rows if necessary
</MODAL>