2025年8月11日月曜日

Excelのピボットテーブルでより自由な集計へ

Excelのピボットテーブルでは、単純な集計なら直観的にできます。
ただ複雑な集計となると、少し直感的でない操作をする必要があるので備忘録。

まずは単純な集計
例えば、以下の2015-2020年の県別人口から、

  
ピボットテーブルで、県別最大人口を出すには、[挿入]メニューピボットテーブルで、
ピボットテーブルをつくり、
ドラッグアンドドロップで、「県名」を「行」の場所に配置し、「人口(千人)」を、「値」の場所に配置し、
「合計/人口(千人)」と表示された部分を左クリックし「値フィールドの設定」から、合計を最大に切り替える。
で基本的な集計はできた。
SQL文で疑似的に書くと以下のような感じ。 SELECT 県名,MAX(人口(千人)) FROM 県別人口 GROUP BY 県名 で本題。以下のような100万人を超えた県には"〇"そうでない県には"×"のようなものを書きたい場合。(SQLでは以下のイメージ) SELECT 県名,CASE WHEN MAX(人口(千人)) > 1000 THEN '〇' ELSE '×' END FROM 県別人口 GROUP BY 県名 どうするかというと、OFFICE2016以降であればDAXでメジャー式が使える、という記事です。 まず、ピボットテーブルを挿入するときに出てくる以下のダイアログで、「このデータをデータモデルに追加する」にチェックを入れておくと、
列をまとめたテーブル名が表示されるようになる
このテーブル名を右クリックし、[メジャーの追加]を選ぶと、集計用の式が書けるようになる。
適当にメジャーを作ってみて、
OKを押すと、メジャーが表示されるようになる。
これを値の部分にドラッグアンドドロップすると、IF条件で表示を〇×に切り替えることができる。

2025年7月30日水曜日

ヘルプページ

ヘルプ開設

2025年7月19日土曜日

PowerBIでRank5以降をその他としてまとめた円グラフの作成(ただしスライサーなど外部フィルターは効かない)

PowerBIでは、
[日付]と[種類]というテーブル(左の表)から、指定期間(上のスライダー)での種類の発生度数を円グラフにすること(中央の円グラフ)は、
簡単な部類ですが、発生度数上位5位以外をまとめてそれ以外をその他とする円グラフにすること(左の円グラフ)は、何をすればよいか
わからず、手が止まってしまう。

いろいろ調べてやれることと限界が見えてきたので、まとめて記事化しておく。 まず簡単とした円グラフですが、元のテーブル
に、メジャー 「MCOUNT種類 = COUNT('テーブル2'[種類])」を追加して、円グラフで使えるようにする。
視覚化で円グラフを選択し、凡例に「種類」、値に「MCOUNT種類」とすると、1つ目の図の中央の円グラフが表示される。
で、ここから問題。 やりたいこととしては元のテーブルに、さらに以下のようなメジャーを追加する。 MRANK種類数 = rankx(ALL('テーブル2'[種類]),[MCOUNT種類]) Mrank5種類 = if([MRANK種類数]<=5,max('テーブル2'[種類]),"その他") MRank5種類順 = if([MRANK種類数]<=5,[MRANK種類数],6) テーブル2から、日付を除く全ての列とメジャーを表示してみると以下のようになる。
上のデータで作りたい円グラフは、[Mrank5種類]を凡例に、[MCOUNT種類]を円グラフの値に、[MRank5種類順]を凡例の表示順にしたもの。 ただ、今回の問題にあたりPowerBIの円グラフでは、凡例にメジャーが使えないことで、ランク5以下の種類をその他とするようなことが難しいという制限がある。 その回避手段として、以下を考えて作ってみる。  サマリーの新規テーブルを作り、Mrank5種類をメジャーでなく、列値として確定してしまう。  この弊害として、サマリーテーブルでは、日付列がなくなる。   →スライサーなど外部フィルターは視覚化部品の描画の直前で適応されるため、サマリーテーブルに指定日付範囲を適用できない。    →外部フィルターの適用は諦め、Filter関数などであらかじめ絞り込まれたテーブルで、サマリーテーブルを作る。 とりあえずやってみる。 まず、1つ目の新テーブルとして、Filter関数で元のテーブルから絞り込みをする。 [モデリング]メニュー→[新しいテーブル]ボタンで、以下の入力をしてみる。 Filteredテーブル = FILTER('テーブル2','テーブル2'[日付]>=dt"2025-6-7"&& 'テーブル2'[日付]<=dt"2025-7-6") (FILTER関数の結果を直でテーブルとして使うことに抵抗があるなら、以下でもいいかな。) Filteredテーブル = CALCULATETABLE('テーブル2','テーブル2'[日付]>=dt"2025-6-7", 'テーブル2'[日付]<=dt"2025-7-6") 追加したFilteredテーブルに以下の3つのメジャーを追加する。 ftMCOUNT種類 = COUNT('Filteredテーブル'[種類]) ftMRANK種類数 = rankx(ALL('Filteredテーブル'[種類]),[ftMCOUNT種類]) ftMrank5種類 = if([ftMRANK種類数]<=5,max('Filteredテーブル'[種類]),"その他") 2つ目の新テーブルとして、サマリーテーブルを作る。 [モデリング]メニュー→[新しいテーブル]ボタンで、以下の入力をしてみる。 sumt = var s1=SUMMARIZE('Filteredテーブル','Filteredテーブル'[種類]) var s2=ADDCOLUMNS(s1,"MCOUNT種類",[ftMCOUNT種類],"種類(上位5個)",[ftMrank5種類],"表示順",[ftMRANK種類数]) return s2 2つ目に追加したテーブルにメジャーを2つ追加する。 Value = sum([MCOUNT種類]) Order =MIN([表示順]) 円グラフに使うデータは以下の、「種類(上位5個)」,「Value」,「Order」。
新しい円グラフをつくり、凡例を「種類(上位5個)」,値を「Value」,ヒントを「Order」とする。円グラフに選択したデータの設定列はこんな感じ。
視覚化部品右上の3点リーダーから、軸の並び替えを選ぶ
で、一番上の右の円グラフが完成する。ただ、今回の対応でサマリーテーブルを作っており、サマリーテーブルを作る時点で日付列がなくなり、[その他]を固定している。 なので、レポートビュー上に配置したスライサーやその他の資格化部品からの相互作用やレポートビュー上のフィルターからの、[日付列]からの絞り込みができず、さらに[その他]列を条件によって変えることができない、という制限がある。 この点で使い物になるのかどうかといったところ。 もっといい方法があるのかもしれないけど、私にはここまででした。 ただ、円グラフなどのような割合を示すグラフなら合計100%に意味があるが、そうでないグラフであれば、その他の集計をしなくてもあまり気にならない気がします。 そもそも3個以上の項目間の比較をする場合、円グラフではなく、棒グラフや折れ線グラフの方が良い気がします。

2025年7月5日土曜日

PowerBI Desktopで、時間単位でのスライサーの小細工

PowerBI Desktopは、以前モダンExcelと呼ばれた Power Query, Power Pivot, Power Viewの部分を取り込み進化させたようなもので、大量データの可視化に優れたツールです。
なので、httpのアクセスログやエラーログ、パフォーマンスログ、各ネットワーク機器の通信ログ、マイクロサービスの各サービスログを連結し可視化することにより分析が捗る気がします。
というわけで、いろいろ使ってみた結果、一番はまった部分である時間単位でのスライサーの部分について、記事化してみます。

スライサーというのは、閲覧者が操作可能なフィルターで、以下の部品です。
これを配置し、スタイルを「指定の値の間」フィールドにdatetime型の列を指定すると、以下のようにカレンダー選択部品付きの日付単位のフィルターになってしまいます。
23:50:02~23:53:10の時間を指定したいのにこれでは、4月3日~6月5日までの日付単位になってしまい、意図したものとはなりません。 ただ数値型のデータに対して、「指定の値の間」フィルターなら以下のように行けそうで、これを使います。
まず、datetime列をもつデータにカスタム列TimeValueを追加します。 以下のように、対象テーブルを選択して、
列の追加ボタンを押します。
数式入力で以下のように、「列 =」の部分を「TimeValue=CONVERT([日時],DOUBLE)」として、
Enterを押すと、データにTimeValue列が表示されます。
これをスライサーのフィールドに指定すると、小数点以下も指定できそうなものになります。
ただ、数字では何日の何時かわからないので、入力テキストボックスを表示せず[日時]列の最小値最大値のメジャーのラベルで日時を表示したい。 入力テキストボックスの非表示はできなさそうなので透明にして、上にラベルを張り付けることにします。 入力テキストボックスの非表示はできなさそうなので透明化は、 スライサーヘッダの表示トグルスイッチをOFF,
フォーマットオプションで、書式をカスタム、形式コードに半角スペースを入れて、表示を無効化する。
表示部品に、「カード」を追加し、データに「日時」列を選択すると、デフォルトで最小値が表示される。
「カード」で、吹き出しの値のフォントサイズを10,カテゴリラペルの表示トグルスイッチをOFF
全般タブの背景の透過率を100%にする。
このカードをコピペして、複製したカードのフィールドの「最も古い日時」の下向きアイコンをクリックして現れるメニューで「最新の日付」から「最初の日付」に変えると、 「フィールド」の表示が、「最新の日時」となる。(最新の日付が最も古い日時で、最初の日付が最新の日時とは?と疑問に思わない)
元のカードとコピペしたカードのサイズをいい感じにして、スライダーの上に配置する。
スライダー表示時に入力テキストボックスがピコピコ表示されないように、「選択項目」を表示させ、「レイヤーの…」のZオーダーをスライサーの上にカードが並ぶようにする。
完成ではあるが、入力テキストボックスが使えず、操作性がよくないので、スライサーを2段階にする。 まずは、スライサー、カード2つを選択、コピーして、
ペーストして、下側に配置する。
上側のスライダーは、下側のスライダーに影響を受けないようにするために、下側のスライサーを選択したのち、メニュー→書式→「相互作用を編集」を押して編集開始する。
選択したスライサー以外の部品について、相互作用の選択ボタンが現れる。コピペした時点で、コピペ元のスライサーには、相互作用なしとなっていてもラベルは連動してしないので、 以下のように上部スライサー、上部最小値ラベル、上部最大値ラベルの相互作用なしマークをクリックする
「相互作用を編集」を押して編集終了し、上部のスライサーを選択し、「相互作用を編集」を押して編集開始し、
下部のスライサーは、上部のスライサーにより、フィルターされるようにする。
「相互作用を編集」を押して編集終了する。 作業をまとめると、以下です。 日時フィールドを数値型に変換し、それをスライサーにすることで、小数点以下の範囲(時分秒の単位)でのスライサーがつかえる。 ただ、数値では時分秒がわからないので、スライサーの値表示ではなく、カードでの表示で日時を表示する。 カードの表示を前面にするため、いろいろ試行錯誤する。(この部分があまりうまく動かないかも) スライダーだけではピンポイントの指定が難しいため、1つは相互作用を受けないスライサー(とラベル)とすることで、2段階のスライダーにする。 今回数値化した日時の値では、1秒加算するためには1/24/60/60=0.00001157...の約0.00001を加算すればよく、 計算により意図した日時に対応する値を求められる。 なので、スライサーの値を(例えばフォントを背景色に合わせることにより)見た目には表示させないが、 数値を入力できるようにしておけば、意図した日時を指定できるので、組み立てが少し複雑な2段階のスライダーはやりすぎかな?

2025年3月20日木曜日

Powershellの配列アクセス

powershellの変数アクセスについてのメモ
定義されている構造とは違う構造でアクセスした場合、読み取りはできるけど、書き込みは有効にならない感じがすることのメモ




要素3つの配列、その要素に要素3つのハッシュがあるものを定義する。
> $person=@(@{id=1;name="Taro";height=175},@{id=2;name="Jaro";height=173},@{id=1;name="Saburo";height=176})


> $person[0]

Name                           Value                                                                                 
----                           -----                                                                                 
name                           Taro                                                                                  
id                             1                                                                                     
height                         175                                                                                   



> $person[0].GetType()

IsPublic IsSerial Name                                     BaseType                                                  
-------- -------- ----                                     --------                                                  
True     True     Hashtable                                System.Object                                             




> $person[0].name
Taro




> $person[0].name.GetType()

IsPublic IsSerial Name                                     BaseType                                                  
-------- -------- ----                                     --------                                                  
True     True     String                                   System.Object                                             



構造通りのアクセスについては予想通り。
配列を無視して1つのハッシュっぽく読み取りアクセスしてみると、


> $person.name
Taro
Jaro
Saburo

> $person.name.GetType()

IsPublic IsSerial Name                                     BaseType                                                  
-------- -------- ----                                     --------                                                  
True     True     Object[]                                 System.Array                                              



> $person.name[1]
Jaro

> $person.name[1].GetType()

IsPublic IsSerial Name                                     BaseType                                                  
-------- -------- ----                                     --------                                                  
True     True     String                                   System.Object                                             

配列を単体のようにアクセスすると、その結果が配列として返却される。
便利な気がするが、(適当に作っても動いてしまって、あとでメンテが辛そうといった)危なっかしい気もする。

次は書き込み。
まずは、構造通りのアクセスで変更してみると、


> $person[0].height
175

> $person[0].height=180

> $person[0].height
180



予想通り変更された。
配列を無視して1つのハッシュっぽく書き込みアクセスしてみると、


> $person.height[0]
180

> $person.height[0]=175

> $person.height[0]
180

エラーは発生せず値は書き換わらない。

> $person

Name                           Value                                                                                 
----                           -----                                                                                 
name                           Taro                                                                                  
id                             1                                                                                     
height                         180                                                                                   
name                           Jaro                                                                                  
id                             2                                                                                     
height                         173                                                                                   
name                           Saburo                                                                                
id                             1                                                                                     
height                         176           

一旦180に書き換えた後に入力した175の値はどこに行っちゃったんだろう。

2025年3月19日水曜日

インタフェース2025年2月号追実行断念。

私にはハードルが高すぎた。
MIKE環境の作成には、・・・を展開します。とあるが、どこからnormal_mike_xxx.tar.gzをダウンロードすればよいかわからない。
第3部4章では、リスト1から14まで参照しているがそのリストがどこにあるかわからない。などなど。
関わっていても時間が溶けるだけで身になることはなさそうなので諦めよう。

2025年3月2日日曜日

マイコン内蔵LEDの接続

インタフェース2月号のラズパイで作り学ぶDockerコンテナの再開。
ページ内で、マイコン内蔵RGBLEDテープを使うところがあり、

秋月電子で、探していたところ、それっぽいものがあった。
https://akizukidenshi.com/catalog/g/g116029/
で、物が届いた後に気が付いた。あれ、これって表面実装部品じゃないですか?
ヒートガンはあるけど、ペーストはんだもない。 というわけで、2.5ミリ間隔の部分にはんだごてでのはんだ付け。 ワイヤストリッパーもないので、被覆をはさみで切りこみを入れたあとねじって引き抜いて、
作業シートの上にセロハンテープで固定して、
老眼鏡をかけてはんだづけ。
以下のページをみて、ピンアサインと配線例を確認し、 https://www.peace-corp.co.jp/data/WS2812B-V5_V1.0_EN.pdf
このページのコードを流用して、 https://howtojp.com/a/sensors/Raspberry-Pi-WS2812B-control import time import board import neopixel # WS2812Bの設定 pixel_pin = board.GP18 # デジタルピン18に接続した場合 num_pixels = 2 # LEDの数 ORDER = neopixel.GRB # カラーオーダー pixels = neopixel.NeoPixel( pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER ) # 色の定義 red = (255, 0, 0) green = (0, 255, 0) blue = (0, 0, 255) # 全てのLEDを順番に点灯 for i in range(num_pixels): pixels[i] = red pixels.show() time.sleep(1) pixels[i] = green pixels.show() time.sleep(1) pixels[i] = blue pixels.show() time.sleep(1) で、動かした結果こんな感じ。
このとき2番目のLEDがなぜか暗かったけど、配線をし直したら明るくなった。 そのほか、BME280もピンヘッダとジャンパをはんだ付けしなきゃならない。インタフェースの特集記事への着手への道のりは先は長そう?