Nova postagem

Pesquisar

Artigo
· Maio 31, 2022 4min de leitura

Embedded Python で IRIS グローバル($LB) を Pandas Dataframe に変換する方法

InterSystems IRIS 2021.2 のバージョンより、Embedded Python を使用できるようになりました。

Embedded Python で Excel のデータを IRIS グローバルに格納する方法 では pandas.DataFrame のデータを InterSystems IRIS グローバルに保存する方法をご紹介しました。
こちらの記事では、その逆の「InterSystems IRIS グローバル($LB) を pandas.DataFrame に変換する」方法をご紹介します。

以下のようなグローバルを、Embedded Python を使用して DataFrame に変換します。

USER>zwrite ^ISJ
^ISJ=4
^ISJ(1)=$lb("Name","Age","Address")
^ISJ(2)=$lb("佐藤","50","東京")
^ISJ(3)=$lb("加藤","40","大阪")
^ISJ(4)=$lb("伊藤","30","京都")


%Library.GlobalクラスのGetクエリ を使用して取得し、iris.sql.execを使用して DataFrame に格納する方法があります。
ただし、こちらの方法はリスト形式($LB)のまま DataFrame に変換します。

USER>do $system.Python.Shell()     // :p でもOK
Python 3.9.19 (main, Oct  3 2024, 14:34:16) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>> mysql = "select name,value from %library.global_get('user','^ISJ()',,2,2)"
>>> resultset = iris.sql.exec(mysql)
>>> dataframe = resultset.dataframe()
>>> print (dataframe)
      name                        value
0  ^ISJ(1)          $lb("Name","Age","Address")
1  ^ISJ(2)          $lb("佐藤","50","東京")
2  ^ISJ(3)          $lb("加藤","40","大阪")
3  ^ISJ(4)          $lb("伊藤","30","京都")
>>>


こちらの結果の value を Name, Age, Address に分けて変換したい場合、既存の %Global.cls のクエリで行うことはできないため、

  1. IRIS側で、あらかじめリスト形式($LB)を分解してから処理する か、
  2. Python側で、IRISのリスト形式($LB)のまま格納されたデータを文字列置換などして DataFrame を作り直す

のどちらかを行う必要があります。

上記1の「IRIS側で処理する」場合、カスタムクラスクエリ を使用してグローバル内のリストの各データを返すクエリを作成し、それをSQL経由でアクセスする方法が考えられます。
カスタムクラスクエリを使用する方法は、SQL文ではなくユーザコードでクラスクエリを記述する方法はありますか? の記事でご紹介しています。

上の記事で紹介しているサンプルクラスを使用して、^ISJ のリストを要素別に抽出するサンプルを作成してみました。

^ISJの value の結果列が$LB形式で3要素なので、上の記事で使用しているサンプルを以下のように変更します。

★GFetchクラスメソッド

//Set Row=$LB($na(@glvn@(x)),@glvn@(x))
 Set Row=$LB($na(@glvn@(x)),$LIST(@glvn@(x),1),$LIST(@glvn@(x),2),$LIST(@glvn@(x),3))

★Gクエリ

// Query G(glvn As %String) As %Query(CONTAINID = 0, ROWSPEC = "Node:%String, Value:%String") [ SqlProc ]
Query G(glvn As %String) As %Query(CONTAINID = 0, ROWSPEC = "Node:%String, Value1:%String, Value2:%String, Value3:%String") [ SqlProc ]


実行例は以下のようになります。

USER>do $system.Python.Shell()     // :p のみでもOK
Python 3.9.5 (default, Apr 15 2022, 01:28:04) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>> mysql="select * from SQLUSER.TestStoredProc1_G('^ISJ')"
>>> resultset = iris.sql.exec(mysql)
>>> dataframe = resultset.dataframe()
>>> print (dataframe)
     node value1 value2  value3
0 ^ISJ(1)  Name   Age Address
1 ^ISJ(2)    佐藤    50      東京
2 ^ISJ(3)    加藤    40      大阪
3 ^ISJ(4)    伊藤    30      京都
>>>


今回使用したサンプルはこちらにあります
 👉https://github.com/Intersystems-jp/GlobalToPandasDataframe
 

~~~

(2022/06/01現在)
日本語対応はしていませんが、以下のような方法もあります。こちらは将来のバージョンで日本語対応予定です。

(2025/01/22現在)
2024.1より日本語対応しました。以下のような方法もあります。

%SYS.Pythonクラスの ToList()メソッドを使用して、IRISリストをPythonリストに変換する方法です。

1.以下のようなクラスを作成します。

Class User.PythonTest Extends %RegisteredObject
{

ClassMethod getDataFrame(gname As %String) [ Language = python ]
{
    import iris
    import pandas as pd
    g = iris.gref(gname)
    cnt=g[None]
    cnt=int(cnt)
    
    newlist=[]
    for i in range(1,cnt+1):
     datalist=iris.cls('%SYS.Python').ToList(g[i])
     newlist.append(datalist)
    newdf=pd.DataFrame(newlist[1:cnt],columns=[newlist[0][0],newlist[0][1],newlist[0][2]])
    print(newdf)
}

}


2.次のように実行します。
  使用するのは、上で使用した日本語データが含まれるリスト形式のグローバル(^ISJ)です。

USER>zw ^ISJ
^ISJ=4
^ISJ(1)=$lb("Name","Age","Address")
^ISJ(2)=$lb("佐藤","50","東京")
^ISJ(3)=$lb("加藤","40","大阪")
^ISJ(4)=$lb("伊藤","30","京都")

USER>:p
 
Python 3.9.19 (main, Oct  3 2024, 14:34:16) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>> iris.cls('User.PythonTest').getDataFrame('^ISJ')
  Name Age Address
0   佐藤  50      東京
1   加藤  40      大阪
2   伊藤  30      京都
>>>
1 Comment
Discussão (1)0
Entre ou crie uma conta para continuar
Artigo
· Maio 25, 2022 2min de leitura

設定されているネームスペース一覧をプログラムで取得する方法

これは、InterSystems FAQサイトの記事です。

%SYS.Namespace クラスの List クエリで取得することができます。

次のようなルーチンを作成し、ターミナルで実行してください。


1. サンプルの作成

getnsp
   // ネームスペース一覧を取得する write "nsp:glo:rtn",!,!
   set statement=##class(%SQL.Statement).%New()
   set status=statement.%PrepareClassQuery("%SYS.Namespace","List")
   set resultset=statement.%Execute()
   while resultset.%Next() {
       write resultset.%Get("Nsp"),!
   }
   quit

 

2. ターミナルから実行

USER>do ^getnsp
%SYS
DOCBOOK
SAMPLES
USER

 


こちらの記事でご紹介しているクラスクエリを実行する方法は、様々なケースで応用できます。

クラスリファレンスをご覧いただくと、様々なクラスクエリをご覧いただけます。
例えば、
 %SYS.DatabaseQuery:GetFreeSpace() データベースの空き容量
 %SYS.GlobalQuery:DirectoryList            データベース内のグローバル名一覧
 %SYS.GlobalQuery:Size                            データベース内のグローバルサイズ一覧
 %SYS.ProcessQuery:SS                           プロセス情報(^%SSユーティリティで確認できる一覧と同じ)
などがあり、様々な情報を取得できます。

他にもいろいろございますので、是非ご活用ください。

Discussão (0)0
Entre ou crie uma conta para continuar
Artigo
· Maio 25, 2022 1min de leitura

如何通过Journal日志文件查询谁对特定数据做了什么操作

%SYS.Journal.Record 类有一个查询(query), List, 可以列出Journal文件中记录的数据修改历史。例如,要查询谁对global节点^QP(1,2)做过修改,可以使用如下代码。它查询Journal文件(输入参数pFilePath)中的global节点(输入参数pSearchGlobal)的操作:

ClassMethod SearchGlobal(pSearchGlobal = "^QP(1,2)", pFilePath = "C:\InterSystems\IRISHealth\mgr\journal\20220525.003")
{
	Set tRS = ##class(%ResultSet).%New("%SYS.Journal.Record:List")
	Set tSC = tRS.Execute(pFilePath)

	While (tRS.Next()) 
	{
		Set address = tRS.Data("Address")
		Set globalNode = tRS.Data("GlobalNode")
		Set newValue = tRS.Data("NewValue")
		Set type = tRS.Data("TypeName")
		Set processid = tRS.Data("ProcessID")
		Set time = tRS.Data("TimeStamp")
		Set globalRef = tRS.Data("GlobalReference")
		
		If globalNode=pSearchGlobal
		{
			W !
			W time,!
			W processid,!
			W address,!
			W type," ",globalRef,"=",newValue,!
		}

	}
}
1 Comment
Discussão (1)2
Entre ou crie uma conta para continuar
Observe que esta postagem está obsoleta.
Anúncio
· Maio 17, 2022

[Video] Securing FHIR Applications with OAuth 2.0 (Part 2)

Hey Developers,

In the second part, you will learn how to build a FHIR Application with OAuth 2.0 and OKTA:

⏯ Securing FHIR Applications with OAuth 2.0 (Part 2)


🗣 Presenter: @Patrick Jamieson, Product Manager IRIS for Health, InterSystems 

Subscribe to the InterSystems Developers YouTube channel and stay tuned!

Discussão (0)1
Entre ou crie uma conta para continuar
Pergunta
· Maio 16, 2022

How to distinguish whether a variable is a pure numeric string or a number, such as "123" and "123".

HI Guys.

I want to know how to distinguish whether a variable is a pure numeric string or a number, such as "123" and "123".

I only know an inelegant way.

ClassMethod IsNumber(n)
{
	s ret=0
	try{
		s ret= $lb(n)=$lb(+n)
	}catch e{
		s ret=0
	}
	q ret
}

Is there any other way to implement it

13 Comments
Discussão (13)2
Entre ou crie uma conta para continuar