大家好,
我有一個創建資料表的 JSL 腳本,並且我在 JSL 腳本中有一個 python 程式碼區塊,我想傳遞資料表以使用訓練有素的機器學習模型對資料表進行預測。在 Python 程式碼區塊之前,DataTable 是可存取的,甚至可以在 JMP 中開啟。但是,在 python 程式碼區塊之後,當我嘗試使用「Show(preds_df)」存取基於 DataTable 的神經網路模型所做的預測時,出現錯誤「名稱未解析:存取或評估『preds_df』時的 preds_df」。我正在使用 JMP Pro 17。下面是我用於審查的程式碼區塊。
<
Clear Log();
Clear Symbols();
Names Default To Here( 1 );
// Define the list of options for the dropdown
SITE = {"SITE_1", "SITE_2"};
MODELS = {"NN_MODEL", "RNN_MODEL"};
PythonConnection = Python Connect();
conn = PythonConnection << Is Connected;
PythonConnection << Send( dt);
close(dt);
PythonConnection << Send(MODELS);
PythonConnection << Execute("
import pandas as pd
from sklearn.preprocessing import StandardScaler
import torch
import pickle
import numpy as np
// Model Selection
if 'NN_MODEL' in MODELS:
model = 'NN_MODEL'
else:
model = 'RNN_MODEL'
# Extract categorical and numerical features from data
categorical_features = ['NAME', 'COUNTRY', 'SCHOOL']
numerical_features = ['AGE', 'SIZE', 'HEIGHT', 'WEIGHT']
# One-Hot encoding for categorical features in place
process_df = pd.get_dummies(dt, columns=categorical_features, drop_first=True)
# Normalize numerical features
scaler = StandardScaler()
new_df[numerical_features] = scaler.fit_transform(process_df[numerical_features])
# Exclude bin columns from the model input
B_cols = ['B1', 'B8', 'B9', 'B10']
B_columns = [col for col in B_cols if col in process_df.columns]
input_df = process_df.drop(B_columns, axis=1)
labels = process_df[B_cols]
ids = process_df[B_cols].index
# Load the trained model based on user selection
if model == 'NN_MODEL':
model_path = '.\\nn_model.pth'
model = torch.load(model_path)
model.eval()
# Convert DataFrame to tensor
in_tensor = torch.tensor(input_df.values, dtype=torch.float32)
# Predict using the model
with torch.no_grad():
nn_preds = model(in_tensor)
nn_preds = torch.round(nn_preds).to(torch.int).numpy()
nn_preds = np.clip(nn_preds, a_min=0, a_max=None)
preds_df = pd.DataFrame(nn_preds.numpy(), index=ids, columns=labels)
else:
model_path = '.\\rnn_model.pkl'
with open(model_path, 'rb') as file:
model = pickle.load(file)
rnn_preds = model.predict(input_df)
rnn_preds = np.clip(rnn_preds, a_min=0, a_max=None)
preds_df = pd.DataFrame(rnn_preds, index=ids, columns=labels)
"
);
Show(preds_df)
>
很快就發現,preds_df 只是一個 pandas 資料框,而不是 JMP 表,因此你無法從 JMP 存取它。
在 JSL 腳本末尾嘗試以下操作:
dt = Python Get( preds_df );
dt << New Data View;
此外,JMP 18 可以本地運行 Python 腳本,因此無需將它們嵌入到 JSL 腳本中。
有沒有辦法將資料框轉換為 JMP 資料表,以便在 python 區塊之外對其進行視覺化。
我收到“Send 期望可編寫腳本的物件在訪問或評估 Send 時,“dt”<< /*###*/New Data View/*###*/”
你可以。我不記得 JMP17 是否能夠直接做到這一點,但您可以例如瀏覽 .csv 檔案:從 pandas 資料框建立 .csv,然後將該路徑傳遞給 JMP 並開啟它。
首先,<
該腳本應該由 JSL 的「原始」字串標記「\[ script here ]\」來描繪,以確保保留空格和行尾。我很驚訝你沒有收到語法錯誤,但是我發現 19 上也沒有同樣的錯誤...我正在調查此事。對我來說,節目 preds_df 只是打印
dt = .;
缺少了。這當然意味著:
dt << 新資料視圖
由於 dt(missing)無法編寫腳本,因此引發錯誤。
下面的程式碼複製了您的問題。
conn = Python Connect();
conn << Get Version();
conn << Execute( "
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print(pandas_df)
]\", echo(1) );
dt = Python Get(pandas_df);
show(dt);
dt << New Data View;
此程式碼按預期運行
conn = Python Connect();
conn << Get Version();
conn << Execute( {},{},"\[
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print(pandas_df)
]\", echo(1) );
dt = Python Get(pandas_df);
show(dt);
dt << New Data View;
需要注意的幾點是,JMP 17 是最後一個在使用者環境中使用 Python 的版本,而不是在 JMP 18 及更新版本中安裝的嵌入式 Python。在 JMP 14-17 中Python Send (dt);透過將資料表儲存到臨時 CSV 文件,然後讓 pandas 將該 CSV 檔案讀入資料框,在 Python 環境中建立了 pandas 資料框。 Python Get( df );行為類似,讓 pandas 將資料框寫入 CSV 文件,並讓 JMP 匯入 CSV 文件。這表示您有 2 份資料副本:JMP 資料表和 pandas 資料框。
隨著嵌入式 Python 3.11.x 和內建跳轉的引入,這種情況在 JMP 18 中發生了變化 導入提供jmp.DataTable類別的套件。這引入了可從 Python 存取的 JMP 資料表的記憶體即時引用。 Python 發送(dt);在 JMP 18+ 中現在建立一個 jmp.DataTable 物件而不是 pandas 資料報。 dt2 = Python Get(dt) 僅取得指派給變數的資料表參考。 dfdt = Python Get(資料框);仍然使用舊的機制透過 CSV 檔案將資料框轉換並載入為資料表。在 JMP 18 中,腳本目錄中有一個 Python 範例腳本,展示如何執行原始 dt->csv->df 和 df->csv->dt 轉換。 JMP 19 支援可移植資料幀協議,因此在記憶體中只需一行程式碼即可轉到 dt->df 或 df->dt。樣本名稱為 dt2pandas.jsl、dt2pands.py、dt2pandas2dt.py
對於 JMP 17:
Names Default to here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
// I have multiple Python's on system so I choose 3.10 where I have
// matplotlib, pandas, numpy, ... installed
Python Init(Use Python Version("3.10"));
Python Send(dt);
close(dt);
dtdf = Python Get("dt");
Show(dtdf);
dtdf << New Data View;
這在我的計算機上運作良好。如果您無法運行它,請檢查您的日誌以查看是否顯示錯誤。如果有必要,請根據您的環境修改 Python Init()。
JMP19
conn = Python Connect();
conn << Get Version();
conn << Execute( {},{},"\[
import jmp
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print( pandas_df )
# JMP 19 create a data table direcly from a dataframe
dt = jmp.from_dataframe(pandas_df)
print( dt )
]\", echo(1) );
show(dt);
// dt << New Data View; // already on screen
只需從編輯器執行 Python 腳本即可完成更多操作,JMP 18+ 中無需 JSL 包裝器