本次演示概述了 JMP 18 對 Python 支援的全新重大更新,這些更新實現了與 Python 更緊密的集成,並顯著提升了以 Python 為中心的用戶體驗。在 JMP 18 中,您將能夠:
這些面向 Python 開放的 JMP 功能將隨著時間的推移而不斷擴展,但目前的重點是關鍵功能和記憶體資料支援。本次演講將詳細介紹這些變化及其背後的原因,並展示 JMP 用戶可獲得的新功能。演講還將探討透過使用外部 Python 套件實現擴充性和資料導入功能,並示範如何使用外部套件透過 Python 介面存取 GPU。
大家好,我是保羅‧尼爾森。今天我想和大家聊聊JMP、Python以及我們的下一步計畫。去年的一次演講之後,我們覺得可以更上一層樓。 JMP和Python還有進步的空間,而這正是我今天要講的內容。
客戶遇到的最大挑戰是 JMP 14 到 17 版本中 Python 支援的問題。如果能正常運行,那當然很好。但實際情況往往並非如此。由於 Python 發行版眾多,環境各異,這給我們的測試工作帶來了極大的困難。
Anaconda 有時可以在 Windows 上運行,Python 虛擬環境有時也可以運行。但由於每個人使用的 Python 版本都不同,因此腳本甚至無法依賴使用者環境中通用的 Python 版本。
在 JSON 編輯器中編輯 Python 程式碼既困難又不方便。 Python 程式碼區塊之間用空格分隔,而當你需要將程式碼區塊貼上到 JSL 中時,這無疑增加了操作難度。此外,舊版 JMP 中 Python 的錯誤報告機制也存在缺陷,使得偵錯 Python 腳本變得異常困難。
最後,資料表和矩陣的傳輸都是透過檔案系統完成的,其中資料表以 CSV 檔案格式傳輸,如果資料量很大,這種方式速度會很慢。處理小類資料沒問題,但處理更大的資料量時速度就會變慢。
我們的目標是確保 Python 整合開箱即用,無需任何配置。為此,我們內建了 Python 3.115 和 JMP 18.0,並將其作為 JMP 的一部分進行安裝。這是一個通用環境,所有使用者都將擁有相同版本的 Python 和 JMP。
我們更進一步,確保 JSL 和 Python 之間的資料流完全在記憶體中進行,並且對記憶體的存取完全零拷貝。我們為 Python 程式設計師打造了一個友善且有效率的工作環境。現在,我們也提供了一個 Python 腳本編輯器,支援程式碼著色和語法高亮顯示。
您可以直接從腳本編輯器執行純 Python 腳本,也可以在 Python 環境中直接存取 JMP 資料和日誌,也可以呼叫 JSL 並從 Python 存取資料。我們大幅增強了 JMP 日誌和嵌入式日誌的錯誤報告功能。
由於現在這是一個通用環境,我們可以對其進行測試和驗證。正如您所看到的,我們的環境與您相同。為了與之匹配,我們在腳本索引中添加了一個完整的 Python 類別…以便解釋並展示 JMP 導入包和其他一些實用包的可用功能範例。
另一方面,這使我們能夠利用 Python 龐大的套件庫來擴展 JMP 的功能。我們並非試圖打造一個完全取代 JSL 的方案,而是力求在 JMP 中為 Python 程式設計提供一個熟悉且高效的環境。
這是一場現代化改造,一場徹底的革新。 JMP Python 整合的一些原始設計決策有其限制。我們已盡一切努力將此次變更帶來的影響降至最低,同時為未來奠定堅實穩定的基礎。
預計此次故障僅限於向 JMP 過渡期間。關鍵在於,我們現在只支援隨 JMP 一起發布的 Python 版本。您可以將其視為一個私有的 JMP 虛擬環境。
腳本中另一個改變是,我們改變了 Python 發送資料表的方式。現在它會建立一個 JMP 資料表物件。這樣就可以即時存取 JMP 資料表。記憶體中的副本可以讓你編輯和修改現有表,它不再是副本。
JMP 14 到 17 版本透過將資料複製到檔案系統中的暫存 CSV 檔案來建立 pandas DataFrame 物件。但對於大型資料集,匯出為 CSV 檔案會變得非常龐大且速度很慢。此外,由於需要在二進位格式和文字格式之間進行轉換,因此也可能存在精確度損失的問題。
如果您確實需要相同的功能,我們在範例文件中提供了一個指向 pandas Python 的 DT(資料樹),其中包含兩個 pandas 函數。它的運作方式與先前內部實作的方式相同:建立一個臨時 CSV 文件,並指示 pandas 匯入該 CSV 檔案。
此外,還有一個 JMP 到 pandas 的範例,展示如何從 JMP 資料表物件在記憶體中建立 pandas DataFrame,該物件一次使用 JMP 列中的一列來建立 pandas 資料列。
Python 的 SendMatrix 函數以前也是透過檔案系統寫入資料的。它會寫入一個包含雙精確度浮點數的文件,然後讓 NumPy 讀取該文件。現在,這個過程在內部記憶體中進行,並且是直接引用矩陣,而不是複製。
JSL Python API 的大部分功能保持不變。此變更主要涉及移除已棄用的參數和函數,這些參數和函數用於配置原始 Python 支援以選擇 Python 版本。
唯一移除的 API 是 Python 的 get graphics 函數,它用於從 Matplotlib 取得映像。在我們的腳本索引中,我們提供了一個範例,展示如何僅使用 JSL 和 Python 程式碼實現 JMP 內部的相同功能。趕緊演示一下吧。我們來看看。退出演示。
這裡是 JMP。我想展示的一點是,您會看到工具列中的 Python 圖標,在“文件”選單的“新建”選項中,我們原本是“JSON 腳本”,但現在是“新 Python 腳本”。我們打開 Python 腳本編輯器。
我們可以使用“顯示嵌入式日誌”功能。我們有一個 JMP 導入套件。導入 JMP。我們已盡力確保添加了 Python 文件字串,以便您可以執行“help JMP Python”命令。我們可以運行該腳本。您會看到,我們已經記錄了此頂級 JMP 導入包中的物件和函數。
這裡有很多常量。大部分特殊目錄都已列出。所以我們可以這樣做。現在我用 Python 執行 JMP 開啟。 JMP,嗯,我今天打字不太方便,JMP。範例資料。另外。 Big Boss。就像在 JSL 中一樣,我們可以選擇程式碼行並在腳本中運行它。我們有一個大類。
現在,這不是副本。我們可以獲得該物件。我們可以執行 `TT = JMP open` 來獲得引用。但我們也可以執行 `TT = JMP.current`。這將給我們一個指向當前資料表的參考。
我們可以列印 TT,這表示這是一個很大的班級,有 5 列和 40 列。但更有趣的是,你還可以列印 TT,表示「姓名」。我們可以使用 Python 的切片操作符。我這裡要列印的是「姓名」欄位中從零開始的每隔一個名字。
在 Python 中,我們使用索引,索引從零開始。我們的資料表索引是按列和行排列的。由於我們採用的是列優先的格式,如果我們印出每隔一個名字,我們會得到 Katie、Jane、Lilly、James、Barbara、Susan、Joe 和 David。
這是即時訪問,所以我們可以做一些事情,例如…我們可以做一些事情,例如TT,我們可以使用名稱或列索引。我們列印列。這樣我們就得到了,選擇。這是你的……我選了一個,對吧,Lewis。抱歉。零零。是Katie。因為數據表是即時的。你可以對Katie執行操作。
稍等。小寫。大小寫混合。現在我們在嵌入式日誌中看到輸出。你會注意到,我們已經修改了數據表。這使你能夠修改資料表,以 Python 的方式存取資料表,並且能夠從 Python 建立資料表。我們已經盡力了。
現在我們有了腳本索引。我會在這裡展示…就像我之前說的,get graphics 函數已經棄用了。它實際上不再是 JMP 中的一個有效函數,但腳本索引中的範例會向您展示如何從先前的方法過渡到 JMP 內部實際實現的方法,即保存圖形、打開圖像並創建一個包含該圖像的新視窗。
Python 環境中一個很棒的新功能是,Python 本身就是一個獨立的類別。 JMP 匯入包包含資料表物件。每個物件都有範例,我們可以建立新列、新增行並儲存表格。它還包含各種屬性,例如取得表名等等。
這條指令會建立一個由 Python 驅動的新資料表。我們還有一個 JMP 工具集。你可以在這裡運行它,或者我們可以用它來運行 pip JMP,因為它創建了自己的隔離環境。當我們安裝軟體包時,它們需要安裝在 JMP 的隔離環境中。
希望您在使用 JMP 時不會遇到軟體包與其他程式或 Python 安裝衝突的問題。我們已經確保它們彼此隔離。所以,如果您確實需要…我們提供了 `create jpip` 命令,它會創建一個腳本來包裝 Python 的 pip 腳本,方便您進行安裝;或者您也可以直接從 gem 包中的 JMP 工具類運行它。
這裡我們將展示如何使用 pip 指令列出已安裝的軟體包。呼叫 pip 並傳回 Python 環境中已安裝的軟體套件清單。另一個例子是,您可以在這裡實際安裝軟體包。這段程式碼可以直接在 JMP 中運行。
這裡有一些注意事項,這也是為什麼需要建立 jpip 套件的原因。如果像 NumPy 這樣的套件載入到記憶體中,因為它使用了共享庫,那麼 Windows 系統可能會阻止你更新該套件。有些套件需要編譯,這些編譯可能需要透過命令列完成。
有些方法可能有效,但可能需要透過命令列運行。因此,你需要建立一個 jpip 包裝腳本。執行該腳本後,會彈出一個窗口,讓你選擇一個目錄來寫入文件,然後選擇該資料夾,腳本就會產生一個可以從命令列運行的 jpip 包裝腳本。
執行該腳本時,安裝完成後需要使用 `---user` 標誌。從這裡呼叫時,我們會自動執行此操作。此外,還有一個 JSL 函數可以執行安裝程式。 Python 安裝套件就更簡單了。您只需執行 JSL 腳本,它就會在背景呼叫 pip,並正確設定所有必要的環境變量,將套件放入 JMP 的隔離環境中。
開始吧。接下來我們可以繼續示範一些其他功能。這些都是簡單的基礎內容。但我們此舉的另一個目的是讓 JMP 對 Python 更加友好,並更容易透過額外的 Python 套件來擴展 JMP 的功能。
使用者經常提出的一個支援需求是匯入 Parquet 檔案。這個演示會從我的硬碟中提取一個表格。這個表格是我從網路下載的。沒錯。然後它會列印出 Parquet 檔案的結構,並根據 Parquet 檔案中的資料逐列建立一個 JMP 資料表。我們會清除日誌。請看我實際操作。
我沒運行腳本。我肯定是高亮顯示了某些內容。好了。這是一個 Parquet 檔案。我們用 Pyrr 製作了 Parquet 文件,因為 PQ 導入了它。這是 Parquet 檔案的屬性。它有一千行。形狀是 13 列乘一千行。架構顯示了列名的架構。
在最底部,我們可以展示另一件事,那就是我們離完成 Python 方面想要改進的事情還差得很遠,但在我們實現目標之前,你可以從 Python 運行 JSL。
儘管 Python 程式碼目前還不支援設定顯示寬度甚至更改列類型等功能,但您仍然可以建立新列,只是無法透過 Python 變更其類型。這些都是我們未來想要實現的功能,但目前您可以透過一種變通方法,也就是像之前在 JSL 中執行 Python 腳本一樣,在 Python 中執行 JSL 腳本。
現在有了這個增強的環境,你可以在兩者之間進行雙向呼叫。 Python 可以運行 JSL 腳本。 Python 中的呼叫隨後可以在 JSL 環境中運行,因此你可以嵌套呼叫來實現原本無法實現的功能。例如,將 JMP 本身不支援的資料類型(例如 Parquet 檔案)匯入到 JSL 中。但我們透過導入一個 Python 套件來實現這一點。
還有一件事我很喜歡。我不太懂統計學,但我精通圖形學和其他數學。這裡我們用的是開放式計算語言(OpenCL)。我們已經導入了 OpenCL 套件。我們要建立一個曼德勃羅集分形。先來看看 CPU 的運作。用 CPU 運作大約需要 16 秒。
這很麻煩,你會注意到 JMP 本身運行緩慢。由於此時 Python 控制著程序,所以它會回應遲鈍。如果你在緊密循環內部深處放置一個運作中的儲存格等待語句,就能重新取得控制權。這裡使用的是 CPU 來產生這個分形。
現在我們改成用GPU運行腳本。搞定!產生影像、儲存影像、在腳本中開啟影像,看看結果如何,只花了不到一秒。用GPU花了16秒……但是,如果我們追溯到更早的時候,就會發現用CPU運行這個腳本實際上花了32秒。
如果你想在 JMP 中使用 GPU,現在可以透過 Python 實作。我們已經測試過 PyOpenCL 和 PyCuda,所以如果你有 Nvidia 顯示卡並且正在使用 CUDA,你可以選擇 PyCuda 或更通用的 OpenCL。這將進一步增強 JMP 的運算能力,避免浪費你桌上型系統的效能。
我們也可以透過 Python 連接到 SaaS。 SaaS 有一個 SaaS y 包,我們已經把它安裝到…這部分工作是我一位同事做的。我們清除日誌。這樣我們就能看到我得到的結果,然後可以執行腳本了。
它正在按預期收集這些資訊。好了。這個腳本實際上使用了 JSL 來確保運行腳本可能需要的所有 Python 套件都已安裝,您可以自行設定。您在日誌中看到的部分內容就是這些套件已經安裝完畢。以下是執行連接到 SaaS 的腳本傳回的所有結果。使用的是 SaaS Py 包,我們稍後會查看日誌。
腳本會回顯到日誌中。就像我剛才說的,我們有連接到 SaaS 平台、運行產品以及我們物流方面的資訊。然後返回輸出值,並結束 SaaS 會話。
我們聽說大家可能對 TensorFlow 有興趣。這裡有一個非常簡單的例子。不對,我已經安裝了 TensorFlow,這段程式碼是在 JSL 中運行的,但我們完全可以直接用 Python 運行這段程式碼。
它運行 TensorFlow,產生這個總和。我相信你會想到比我演示的更複雜的用法。 Py Digest 是另一個例子。它就像一個螢幕。這裡有一個我創建的範例,展示了它的幾個功能,包括運行 JSL,它允許我使用 JMP 的 pick directory 函數選擇一個目錄,然後使用 JSL pick directory 函數在 Python 腳本中使用它。這完全是純 Python 腳本。它允許我選擇一個目錄。
它會計算目錄中每個檔案的校驗和,並將校驗和存入 SQLite 資料庫,然後根據資料庫建立 JMP 資料表。這能讓你接觸到一些資料庫程式設計知識,以及一些 JMP 程式設計技巧,例如如何使用 Python 建立 JMP 資料表和運行 JSL 程式碼。
選擇目錄。這裡有很多數據,所以我們先選擇要展示的 Parquet 資料夾或 Select 資料夾。現在我們有了一個校驗和表格。他們創建了…它會檢查目錄中的每個文件,並提供它們的路徑名和文件內容的 MD5 校驗和。建構了資料庫。使用 Python 建立了 JMP 資料表,並使用 JSL 設定了列寬。
再次強調,我們尚未實現此功能,但已將其列入考慮範圍。不過,如果您願意,您可以透過 Python 程式碼執行 JSL 操作。
有些人可能想用 R 語言。好吧,在這種情況下,我已經在我的機器和我們的環境中,使用我們的伺服器建立了連接。在 Windows 系統上運行我們的伺服器來運行 Linux WSL 環境要容易得多。
我這裡運行著一個 R 伺服器守護進程,並使用預留的客戶端。我正在做一個簡單的操作:在伺服器上建立一個 R 向量,計算結果並加總,然後執行這個腳本。我們已經連接到伺服器,獲取了向量,並將所有元素相加得到 6。我們的 py2 版本也有一些範例。如果您想要一個非常簡單的、可以從命令列運行的 R 範例,這裡有一個如何使用進程從命令列呼叫並執行 R 的範例。
最後是統計部分,Jon Saul 幫了他不少忙。他創建了一個使用 HDB scan Python 套件的範例。關於 Matplotlib 需要注意一點:Windows 上的 Matplotlib 沒有圖形後端,所以如果想要看輸出,我們會發現 PyQt5 的效果最好。
作為後端,在 Mac 上,如果您使用 Matplotlib,我們會強制它使用 AGG(非圖形後端),如果您尚未安裝 PyQt5 或 PySide。這是因為 Mac 上的 Matplotlib 會自動選擇 Cocoa 後端,而 Cocoa 後端存在一個 bug:當您在 Mac 上關閉 Matplotlib 的最後一個視窗時,會導致 JMP 退出。
為了防止強制使用的情況,如果我們在您的系統上找到 Matplotlib,並且它有後端,我們會載入 Matplotlib 並強制它使用 Qt 後端。否則,我們會確保它是一個非圖形後端。我們已經將其設定為後端。我的機器上安裝了 PyQt5。在這個範例中,我們對 HDB 掃描進行了一些聚類分析。
現在我們來展示一下嵌入的日誌。我們將運行腳本。結果會得到一個用 Matplotlib 產生的資料表格。這裡可以看到我們使用 JMP 開啟了文件,並取得了 DT 參考。這些就是我擁有的樣本。相信我。
我將重新介紹簡報。我們近期工作的重點是:持續改進和完善;提升 JMP 和 Python 之間的資料互通性。目前,列修改編輯的限制在於,雖然可以建立任何類型的列,但只能修改和取得數值列、字元列、表達式列或狀態列的值。創建連結表的功能將在未來實現。
雖然 Python 腳本編輯器支援程式碼著色和語法高亮,但目前還不支援自動縮排。我們也會研究這個問題。
現代化的目標是讓 JMP 與 Python 的整合開箱即用。使用者無需任何配置即可有效率地使用 JMP 和 Python。如果集成失敗,將會非常棘手。為什麼不縮短 Python 程式設計師在 JMP 中投入工作的時間,並提升 JMP 的功能呢?使其能夠輕鬆擴展,利用外部 Python 套件,從而成為一個強大的分析中心。
提升我們載入不同資料格式的能力,例如我們已經測試過的 Parquet 格式和 HDF5 格式。現有的資料格式種類繁多,任何一個開發團隊都無法全部編寫,但透過這種方式,您可以引入 Python 包,並將其轉換為 JMP 資料表,從而在 JMP 中實現強大的資料處理能力。
感謝您抽出時間。希望您喜歡我們的作品,非常期待您的回饋。謝謝。