JMP 18과 내장된 Python 기능은 많은 오픈소스 도구에 대한 액세스를 제공하여 SAS를 포함한 여러 데이터 소스와 상호 작용할 수 있는 문을 엽니다! 오픈소스 Python 패키지 SASPy를 JMP 환경에서 어떻게 활용할 수 있는지 살펴보겠습니다. 이 튜토리얼에서는 다음을 수행합니다.
- SASPy를 설치하세요.
- Python 스크립트를 사용하여 SAS에 연결합니다.
- SAS에서 데이터 세트를 다운로드하고 엽니다.
- SAS에 테이블을 업로드합니다.
- SAS 코드를 실행합니다.
펀치라인에만 관심이 있다면 전체 예제 스크립트에 대한 첨부 파일을 참조하세요. 하지만 JMP에서 Python을 사용하는 방법에 대한 리프레셔가 필요하다면 도움이 될 수 있는 몇 가지 블로그 게시물이 있습니다.
JMP® 18에서 Python 통합 시작하기
Python으로 구현된 JSL 함수 생성
SASPy: SAS와 JMP 연결
SAS에서 관리하는 오픈소스 SASPy를 사용하면 Python을 사용하여 SAS와 인터페이스할 수 있습니다. SASPy는 SAS Viya 연결과 Integrated Object Model(IOM)을 사용한 로컬 및 원격 연결을 지원합니다. 연결에 따라 강력한 API를 사용하여 SAS 라이브러리 목록에 액세스하고, 라이브러리 정보, 목록 테이블 및 테이블 정보를 가져오고, 개별 열 정보를 가져오고, 테이블을 다운로드하고, pandas DataFrames에서 변환하고, SAS 코드를 실행하고, SAS 로그에 액세스하고, SAS 통계 및 머신 러닝 절차를 활용하고... 지금은 이것으로 충분할 것입니다.
JSL을 사용하여 SASPy 설치
JSL-land에서 시작해 봅시다. 튜토리얼을 위해 numpy, pandas, SASPy가 필요합니다. 다음 JSL 스크립트를 실행하여 필요한 패키지를 설치합니다.
Names Default To Here( 1 );
// install numpy and pandas packages
Python Install Packages( "numpy pandas saspy" );
로그를 보고 패키지가 올바르게 설치되었는지 확인하십시오. 설치된 패키지는 재시작 사이에 JMP에 유지되므로 한 번만 설치하면 됩니다(성공했다고 가정).
Python을 사용하여 SAS에 연결
연결하려면 SAS 인스턴스에 대한 정보를 알아야 합니다. 즉, 어떤 유형의 연결을 사용할 것인지(Viya 대 IOM), SAS 서버의 위치, 그리고 액세스하는 데 필요한 자격 증명입니다.
SASPy는 매우 구성 가능하므로 특정 연결 시나리오에 대한 SASPy 설명서를 참조하세요. 두 가지 방법을 사용하여 연결하는 방법을 다룹니다.
- Viya는 http를 사용하여 Viya 인스턴스에 연결하며 Java 설치가 필요 없습니다. SAS 9.4에서는 작동하지 않습니다.
- IOM은 컴퓨터에 Java가 설치되어 있어야 합니다. Windows에서 로컬 인스턴스에 액세스하거나 모든 플랫폼에서 원격 인스턴스에 액세스할 수 있습니다.
사전을 사용하여 연결
JMP Python 스크립트 창을 열어서 시작합니다. 또한 마우스 오른쪽 버튼을 클릭하고 "Open Log"를 선택하여 임베디드 로그를 엽니다. 아래 스크립트는 연결 매개변수가 포함된 Python 사전을 사용합니다. 매개변수를 SAS 인스턴스에 고유한 매개변수로 바꾸면 연결할 수 있습니다. SASSession의 변수를 연결 유형에 해당하는 사전으로 바꾸고, 마우스 오른쪽 버튼 메뉴를 사용하여 임베디드 로그를 열고 실행합니다.
보안에 대한 참고 사항: 아래 기술은 SAS 연결을 확인/디버깅하는 데 도움이 될 수 있지만, 권한을 엄격하게 제어할 수 있는 별도의 파일에 자격 증명을 저장하는 것이 더 나은 옵션일 수 있습니다. 조직의 보안 정책에 대해 확신이 서지 않으면 시스템 관리자에게 지원을 요청하세요. 아래 단계를 통해 연결할 수 있다면 계속 진행하세요. 그런 다음 "구성 파일을 사용하여 연결" 섹션의 단계를 사용하여 스크립트에서 자격 증명을 이동하세요.
또 다른 참고사항: JSL에서 Python을 실행할 수 있으며 그 반대의 경우도 가능합니다. 따라서 코드를 실행할 때 Python을 실행할지 여부를 판단하기 위해 파란색과 노란색 Python 로고가 있는지 모서리를 확인하세요.
마지막으로, JMP는 실행 중에 Python 스크립트에 제어권을 넘기므로 코드가 실행되는 동안 GUI가 응답하지 않는 것이 일반적입니다.
import saspy
viya = {
'url' : 'https://notrealsas.jmp.com:1234', # must contain http or https
'user': 'username',
'pw' : 'password',
'verify' : True, # verify certificates
}
iom = {
# location of java on your machine
'java': r'C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe',
}
iom_remote = {
'java': r'C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe',
'iomhost': 'notrealsas.jmp.com',
'iomport': 1234,
'omruser': 'username',
'omrpw': 'password',
}
# connect to SAS
# replace the second argument with your connection dict, mind the **
sas = saspy.SASsession(prompt=False, **viya)
print(sas)
연결이 성공하면 내장된 로그에 다음과 유사한 내용이 표시됩니다.
SAS Connection established. Subprocess id is 10040
Access Method = IOM
SAS Config name = default
SAS Config file = C:\Users\you\AppData\Roaming\JMP\JMP\Python\Python311\site-packages\saspy\sascfg.py
WORK Path = C:\Users\you\AppData\Local\Temp\SAS Temporary Files\_TD16996_SAS-PF4H167P_\Prc2\
SAS Version = 9.04.01M8P01182023
SASPy Version = 5.10.0
Teach me SAS = False
Batch = False
Results = Pandas
SAS Session Encoding = wlatin1
Python Encoding value = cp1252
SAS process Pid value = 16996
연결할 수 없는 경우, 단서를 찾기 위해 로그를 주의 깊게 읽고, 사용자 이름과 비밀번호도 확인하세요(해당되는 경우). 코드를 실행하기 전에 내장된 로그를 열면 인쇄 명령문과 예외가 표시됩니다. 연결이 실패할 수 있는 다른 일반적인 이유는 다음과 같습니다.
- 을 통해
- SAS의 URL 주소에 접근할 수 없거나 철자가 틀렸습니다.
- 'url' 매개변수를 http(s):// 로 포맷하지 못했습니다. : 예 를 들어 , http://server.jmp.com:5432
- SAS 인스턴스가 자체 서명된 인증서를 사용하는 경우 '확인' 필드를 "true"로 표시합니다(경고: verify=false로 연결하면 보안 위험이 발생할 수 있음).
- 국제이주기구(IOM)
- Java가 설치되지 않았습니다(Java를 설치한 후 JMP나 컴퓨터를 다시 시작해야 할 수 있음).
- Java 실행 파일의 경로가 잘못되었습니다. JAVA_HOME(Mac)의 환경 값을 보거나 java 폴더(Windows)의 경로를 검색해 보세요.
구성 파일을 사용하여 연결
이제 연결 정보를 다른 곳으로 옮겨보겠습니다. 다시 한 번, 시스템 관리자에게 연락하여 조직의 보안 관행을 준수하도록 하세요. 이 게시물에 첨부된 예시 구성 파일(sascfg_personal.py)을 다운로드하고 값을 자격 증명으로 바꾸세요. 이 파일의 SAS_config_names를 기록하여 연결 옵션이 해당 목록에 있는지 확인하세요. 그런 다음 파일 위치를 사용하여 연결하세요.
import saspy
# replace with path to your config file
config_file = r'/some/path/to/your/config/sascfg_personal.py'
# replace the cfgname argument with the connection in your config file
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
print(sas)
출력은 이전에 연결했을 때와 동일해야 합니다.
데이터 세트 열기
파일을 다운로드하여 데이터 세트 열기
SAS 데이터 세트를 가져오는 한 가지 방법은 파일을 직접 다운로드하는 것입니다. JMP는 데이터 세트 파일 유형(sas7bdat)을 가져올 수 있으며, 이는 데이터 형식과 레이블을 보존하는 데 도움이 됩니다. 아래에 표시된 Python 스크립트는 SAS에서 파일을 다운로드하고 Python 스크립트 내에서 JSL을 사용하여 파일을 엽니다.
import saspy
import jmp
import tempfile
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
print("Connected to SAS", sas)
table_name = 'cars'
library_name = 'sashelp'
print('Download ' + library_name + '.' + table_name)
data = sas.sasdata(table_name, library_name)
metadata = data.contents()
remote_file = metadata['Enginehost'].query('Label1 == "Filename"')['cValue1'].item()
# save in temp
tmp_dir = tempfile.gettempdir()
print('Copying ' + remote_file + ' to ' + tmp_dir + '...')
sas.download(tmp_dir, remote_file)
print('Opening table...')
jmp.run_jsl('''
dt1 = Open(
"%s/cars.sas7bdat",
Use Labels for Var Names( 1 )
);
''' % (tmp_dir) )
Cars 데이터 세트의 데이터가 포함된 데이터 테이블이 열리는 것을 볼 수 있습니다.
pandas DataFrame을 사용하여 데이터 세트 열기
SASpy를 사용하면 데이터 세트를 pandas DataFrame에서 변환하거나 pandas DataFrame으로 변환할 수 있습니다. 이는 데이터 파이프라인의 일부로 사용하여 변환, 정리, 데이터 생성 등을 수행할 때 유용합니다. JMP 자체도 pandas DataFrame을 JMP 테이블로 가져올 수 있으므로 가능성이 더욱 커집니다.
아래 Python 예제에서 SASHELP.class 데이터 세트를 DataFrame으로 열고 JMP 테이블을 열고 정의된 유틸리티 함수 dataFrameToJmpTable()을 사용하여 DataFrame의 값으로 JMP 테이블을 채웁니다.
import saspy
import jmp
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
def dataFrameToJmpTable(dataFrame, table):
# Populate a jmp data table with a pandas dataframe
# Credit: Paul Nelson
cols = dataFrame.columns
values = dataFrame.values
for (i,k) in enumerate(cols):
print(i, k, dataFrame[k].dtype)
l = values[:,i].tolist() # turn pandas (numpy) column to a list
# create new columns based on the data type of the pandas column
value = values[0,:][i] # get example value from the i'th column
print("Example value: ", value)
if dataFrame[k].dtype == object and isinstance(value, str):
table.new_column(k, jmp.DataType.Character)
table[k] = l
elif dataFrame[k].dtype == 'float64': # numpy.number:
table.new_column(k, jmp.DataType.Numeric)
table[k] = l
elif dataFrame[k].dtype == 'int64': # or 'int32'
table.new_column(k, jmp.DataType.Numeric, dlen=4)
table[k] = l
else:
print('Unhandled column type: {dataFrame[k].dtype} . Defaulting to string.')
table.new_column(k, jmp.DataType.Character)
table[k] = l
sasData = sas.sasdata('Class', 'SASHELP',
results='pandas',
# dsopts={'where':'Age > 12',}
)
dataFrame = sasData.to_df()
values = dataFrame.values
num_rows = len(values)
dt = jmp.DataTable(name='Class', rows=num_rows)
dataFrameToJmpTable(dataFrame, dt)
성공하면 열린 Class 데이터 테이블이 표시되어야 합니다.
SAS에 파일 업로드
데이터 세트를 다운로드하는 것과 유사하게, SASPy에서 제공하는 DataFrame 인터페이스를 사용하여 SAS로 데이터를 다시 업로드하거나 JMP 파일을 업로드할 수 있습니다. 다음은 JMP 데이터 테이블 파일을 SAS로 업로드한 다음 SAS 프로시저 PROC IMPORT를 사용하여 가져오는 예입니다.
import saspy
import jmp
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
table_name = 'animals.jmp'
remote_file = sas.workpath + table_name
local_file = jmp.SAMPLE_DATA + table_name
results = sas.upload(local_file, remote_file, overwite=True)
print(results)
# import uploaded file as a data set, replace data set if existing
command = '''
PROC IMPORT OUT= WORK.animals
DATAFILE="{jmp_file}"
DBMS=JMP REPLACE;
RUN;
'''.format(jmp_file=remote_file)
results = sas.submit(command)
print(results)
내장된 로그를 확인하거나 파일을 다운로드하여 제대로 작동하는지 확인하세요.
아래는 DataFrames를 사용한 업로드 전략입니다. 먼저 JMP 테이블을 DataFrame으로 변환한 다음 dataframe2sasdata()를 사용하여 업로드합니다.
import saspy
import numpy as np
import pandas as pd
config_file = r"C:\Users\user\Documents\sascfg_personal.py"
sas = saspy.SASsession(prompt=False, cfgname='iom', cfgfile=config_file)
def jmpTableToDataFrame(dt) :
# Credit to Paul Nelson again
# Creating a Pandas dataframe from a JMP DataTable
df = pd.DataFrame()
for idx in range( len(dt) ):
if dt[idx].dtype == jmp.DataType.Numeric:
# creates numeric column directly using Python's Buffer Protocol
col = np.array( dt[idx] )
df[ dt[idx].name ] = col.tolist() # make it a list for pandas.
elif dt[idx].dtype == jmp.DataType.Character:
# create a list by iterating through values
col = list()
for i in range ( dt.nrows ):
col.append(dt[idx][i])
# Build character column from list
df[ dt[idx].name ] = col
else:
print("Not adding type:", dt[idx].dtype )
return df
data_table = jmp.open(jmp.SAMPLE_DATA + "Fitness.jmp")
df = jmpTableToDataFrame(data_table)
result = sas.dataframe2sasdata(df, 'Fitness', 'WORK')
print('WORK Tables:', sas.list_tables('WORK'))
내장된 로그를 확인하여 Fitness 테이블이 WORK 테이블 목록에 표시되는지 확인하세요.
제 경험상, 업로드/다운로드 전략에 전체 파일을 사용하는 것이 두 전략 중 더 빠른 경향이 있습니다. 또한 데이터 변환이나 표현 문제를 제한합니다. 반면에 DataFrames는 다른 Python 모듈에서 널리 수용됩니다. 데이터에 대한 추가 Python 작업이 필요하지 않은 한 파일 전략을 사용하는 것이 좋습니다.
SAS 코드 실행
마지막 섹션에서는 sas.submit() 함수를 사용하여 SAS 코드를 실행하여 파일을 가져왔지만, 모든 SAS 코드로 이를 수행할 수 있습니다. JSL 스크립트 내에서 SASPy를 사용하고 SAS 코드를 실행하여 클래식 SAS 그래프를 만들고 보는 방법을 보여주는 예제는 첨부된 saspy_cowboy_hat.jsl을 확인하세요. 출처: @브라이언_분 및 @크리스헤메딩거 .
JMP 19를 기대하며
JMP 18에서 SASpy를 사용하는 스크립트, 애드인 및 파이프라인은 JMP 19에서도 계속 지원되므로 SAS로 작업할 때 생성된 모든 인프라를 계속 사용하고 구축할 수 있습니다. 또한 JMP 19는 SAS 통합과 관련된 여러 기능을 제공하여 이 게시물에서 언급한 스크립트와 기술을 더욱 보강합니다. SAS 내보내기 대화 상자 및 다양한 JSL SAS 통합 기능과 같은 일부 친숙한 기능이 다시 제공됩니다. 이러한 기능은 모두 데이터 커넥터 인프라를 기반으로 구축되어 조직 전체에서 SAS 연결을 쉽게 구성, 공유 및 활용할 수 있습니다.
현재 JMP 18을 사용하고 있으며 JMP 19가 프로덕션에 들어가기 전에 향후 SAS 통합 기능을 시도하고 싶으신가요? 집중적인 피드백과 방향을 제공하는 좋은 방법은 JMP 19 Early Adopter(EA) 프로그램에 지원하는 것입니다. 자세한 내용은 jmp.com/earlyadopter를 방문하세요.
Python이 제공하는 강력한 오픈소스 도구를 JMP에 통합하면 데이터에 액세스하고 상호 작용할 수 있는 많은 기회가 제공됩니다. 전체 SASPy 데모 스크립트는 이 게시물에 첨부되어 있습니다.
또한, SASPy를 지원해 주신 Tom Weber에게 큰 감사를 전합니다. 오픈 소스 패키지로서, github에서 SASPy 에 대한 개선 사항이나 제안을 기여하는 것을 고려하세요.
모두 스크립팅을 즐기세요!
자원
SASPy 구성
SASPy 파이썬 API
SASPy 예제 Jupiter 노트북
판다스 문서