みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Pages: 1
いつもお世話になっております。かって最頻値を求めるため試した方法で条件を変えたところパーフォーマンスが悪くなったので最適な方法がないものかと思い質問いたしました。
レコード数100万でフィールドの値をアルファベット1文字から4文字に変更。
テーブル構成
・item(text)
・count(集計、カウント・すべて同時・ 集計フィールド: item)・・・普段表示せず
・計算結果(text,グローバル)
スクリプト
レコードのソート [ 特定のソート順: 統計data::item; 降順; 集計フィールドに基づいて並べ替え: 統計data::count ] [ 記憶する; ダイアログなし ]
レコード/検索条件/ページへ移動 [ 最初の ]
変数を設定 [ $k1; 値:統計data::item ]
変数を設定 [ $k2; 値:GetSummary(統計data::count;統計data::item) ]
変数を設定 [ $k3; 値: $k1&Char(9)& $k2 ]
Loop
If [ 統計data::item = $k1 ]
Exit Loop If [ Let ( $next = Get ( レコード番号) + $k2 ; $next > Get ( 対象レコード数) ) ]
レコード/検索条件/ページへ移動 [ $next ] [ ダイアログなし ]
Else
Exit Loop If [ $k2 > GetSummary (統計data::count;統計data::item ) ]
変数を設定 [ $k1; 値:統計data::item ]
変数を設定 [ $k3; 値:$k3& ¶ & $k1&Char(9)& $k2 ]
End If
End Loop
フィールド設定 [ 統計data::計算結果; $k3 ]
初回を除いた5回平均で34.486(参考:同じデータをmysql8.0に入れ over()で求めた場合 2.228、pythonでcsvファイルを使って求めた場合 0.659)
1文字の場合 5回平均 6.807
レコードを一旦csvファイルにエクスポートしてpythonで処理しインポートする方法も試したがスクリプトの停止(時間が最低でも2秒弱必要)を入れないと最新の処理結果がインポートされない場合が発生、文字の組み合わせにもよるがエクスポートの時間を含めても5.9台となるがいまいち動作に不安があり、レコード数が少ないならExecuteSQLでも気にならない処理時間だが多くなるととんでもない時間がかかるので他にfilemakerだけでもっとパフォーマンスが上がる方法ないかご教授お願いいたします。
ちなみに、4文字の組み合わせは、pythonでランダムな文字列を生成しcsvファイルに書き込む方法を試した結果です。
何のループなのかわかりません。最頻値なら集計をソートすれば1行目を見るだけでいいのでは?
himadaneeさん、ご指摘の疑問につきましては、複数の最頻値があった場合を想定しています。
ソートだけで約27秒なので、ソートしないでできるかやってみましたが、100万レコードスキャン(レコード移動)するだけで約14秒かかりました。
レコードを移動せずにGetNthRecordを使ってみたら(フィールド値を変数に入れるだけ)、1万レコードなら3秒で終わったのが、10万だと急に5分以上かかるようになりました。これは使えない...
(1つの変数に上書きで入れてるだけなので、変数の数は変わってません)
himadanee様、レコードの移動を問題視されているようですが、前回の方法でランダム文字列を生成しても最高頻度が15以下の状態が多く最頻値は時に11個ぐらいはありましたが、試した回数が少ないためか大きなバラツキが見られないように思えました。レコードの移動時間がを問題になるとは思えませんでした。そこで下記のデータを作り計測してみました。
100万レコードの内訳は、
ユニーク文字列
390996
最頻値と頻度
VSDX 40001
GWXT 40001
結果
平均計測値
24.884
ファイルも新しくしたためか前回より改善されていました。原因についてはよく理解が出来ません。後書き忘れていましたが環境はwin10でメモリは32.0 GB FM19です。winだから遅いのかも?
いえ、レコード移動とGetNthは、FMはソート自体が遅いので、何か他の方法で早くできないかという実験です。
ちなみにレコード移動中に大量の変数に取り込んで1パスで結果を得るというのもやってみましたが、11分ぐらいかかりました。
というわけで今のところあんまりいい方法は見つかっていません。
ExecuteSQLやループスクリプトなど100万レコードで色々試した中で、最もパフォーマンスが良かった方法です。
「フィールド内容の全置換」をグローバルフィールドに適用するだけの至って簡便な方法です。
【設定手順】
itemフィールドは索引済であること
itemフィールドで照合する自己リレーション「テーブル 2」を設定しておく
結果を格納するグローバルフィールド「result」を用意する
「result」に計算値による全置換を掛けて結果を代入します
その式は、
Let(
[
#cnt=Count(テーブル 2::item);
$itm=Case(
$cnt=#cnt; List($itm; Case(FilterValues(テーブル::item;$itm)=Char(0); テーブル::item));
$cnt<#cnt; テーブル::item;
$itm);
$cnt=Max($cnt; #cnt)
];
Case(Get(レコード番号)=Get(対象レコード数); List($cnt;$itm)) //最後のレコードになったら最終結果を書き出す。
)
Offline
Hiro様 「フィールド内容の全置換」方法ありがとうございます。
自己リレーションをフィールドf1同士を=で結び下記の全置換えスクリプトで実行したところ 最頻値が9個とと頻度が11の結果が出ましたが私の作り方が間違っているのか処理時間が80秒台となりました。
フィールド内容の全置換 [ test001::result; 計算で置き換える: Let( [ #cnt=Count(test001 2::f1); $itm=Case( $cnt=#cnt; List($itm; Case(FilterValues(test001::f1;$itm)=Char(0); test001::f1)); $cnt<#cnt; test001::f1; $itm); $cnt=Max($cnt; #cnt) ]; Case(Get(レコード番号)=Get(対象レコード数); List($cnt;$itm)) //最後のレコードになったら最終結果を書き出す。 ) ] [ ダイアログなし ]
f1フィールの状態
入力値の自動化:
編集を許可
入力値の制限:
データの入力時のみ
データの格納:
繰り返し: 1
索引: 最小限
必要時に索引を自動作成
索引設定言語: 日本語
私のソート方法では同じデータで初回は42秒台でしたが後は33~35秒台でした。間違った点のご教授お願いします。
非効率と思われる「集計フィールド」や「リーレーション集計」の代わりに、ソート下を前提にした全置換式です。
結果はどうでしょうか?
Let(
[
#flg=test::item<>$val;
#cnt=Case(#flg; $num);
$num=Case(#flg;1;$num+1);
$val=test::item;
$itm=Case(#flg; Case(#cnt=$cnt;List($itm;$val); #cnt>$cnt;$val; $itm); $itm);
$cnt=Max($cnt; #cnt)
];
Case(Get(レコード番号)=Get(対象レコード数); List($cnt; $itm))
)
Last edited by Hiro (2021-05-18 15:41:22)
Offline
Hiro様 単純に前回の置換えの計算式を変えてみましたが、最頻値でない値が3個と頻度2が結果として表示されました処理時間は66~40秒台ちなみにリレーションの有無は関係無いですよね。同じ結果が返ってくので
間違えた
66~70秒台です
4文字のテキストフィールドだけエクスポートするんだと、うちの環境でも4秒しかかかりませんでした。結果のテキストファイルのサイズが10MBそこそこにしかならないので、意外に速いんですね。(通常こんなエクスポートはしないので、もっとかかるものと思ってた)
フィールドを全部エクスポートすると180MBぐらいで17秒ぐらいかかりました。
グローバルフィールドの全置換は、定数(1)に置換しても20秒かかりました。
昔はこれが結構速かった気がしたんだけど...いつのバージョンだったか、何かのテストで思ったより遅くてがっかりした記憶があります(曖昧過ぎる話で恐縮です)。
「計算結果を挿入」に変数が使えるようになった頃で、バージョンは17だったようです。これですね(英語ですが)
https://community.claris.com/en/s/quest … mance-leap
全置換との比較がコメントにありますが、あいにくcommunityの変更前だったようでリンク切れになっています。
これはループというより巨大なテキストの生成に関する話題なので、今回の最頻値を求めるのとはちょっと違いますね...
(結果を得るのに連結したテキストは必ずしも必要ないが、全データを外部に出すとすると必要になる)
himadanee様 様々な情報有り難うございます。
別のwebビューアとjavascriptの計算値に関する質問で最頻値を求めてみました。計測結果は、5回平均5650ミリ秒でした。
https://fm-aid.com/bbs2/viewtopic.php?id=11901
Pages: 1
[ Generated in 0.008 seconds, 9 queries executed - Memory usage: 553.54 KiB (Peak: 574.45 KiB) ]