エクセル関数応用
「Python in Excel」で自作関数を登録
アンピボット関数と計算順序

Excel関数の解説、関数サンプルと高等テクニック
公開日:2026-08-12 最終更新日:2026-08-12

「Python in Excel」で自作関数を登録|アンピボット関数と計算順序


クロス集計表(マトリクス表)をリスト形式(縦持ちデータ)に変換するアンピボット処理。
Python in Excel(=PY)を使えば、汎用的なアンピボット関数を1つ定義しておくだけで、ブック内の複数の場所から呼び出して使い回せるようになります。


ここで紹介するPythonコードは、行ヘッダーが何列になろうと列ヘッダーが何行になろうと、引数の範囲指定を変えるだけでコード自体は一切変更せずにそのまま適用できる柔軟性を備えています。

本記事では、Python in Excelで作成したアンピボット関数 「unpivot」 のコード構造を詳細に解説するとともに、自作関数や変数を別セルから利用する際に不可欠となる「Excelの計算順序(評価順序)」と「シート配置」のルールについて解説します。

※本記事のPythonコードおよび解説文章の多くは、生成AI(ChatGPT、Gemini、Claude)を活用して作成しました。Python動作や解説文の最終的な内容は人間による確認・編集を経て掲載しています。

ページ内目次

変換イメージ

【変換前:クロス集計表】

「Python in Excel」で自作関数を登録

【変換後:アンピボット(縦持ちのデータ)】

「Python in Excel」で自作関数を登録


「Python in Excel」でアンピボット

まずは、特定のセル範囲を直接指定して単体セルで動作させる基本的なコードを作成します。

r, c, v = xl("A3:B6").values, xl("C1:F2").T.values, xl("C3:F6").values
pd.DataFrame([[*rv, *cv, val] for rv, row in zip(r, v) for cv, val in zip(c, row)])

「Python in Excel」で自作関数を登録

変数への代入時にあらかじめ .values や .T(転置)の処理を済ませておくことで、リスト内包表記の中身は zip(r, v) や zip(c, row) となり、非常にシンプルで直感的な記述になります。
※コードの詳細解説は後程、関数化した後に掲載します。

上記のコードでアンピボット処理自体は完了します。
しかし、この単体コードのまま運用しようとすると、実務では以下のような課題に直面します。

なぜ関数化したいのか(単体コードの課題)
  • コードのコピペ・二重管理が発生する(DRY原則の違反)
    別のシートや別のセル範囲でアンピボットを行うたびに、同じPythonコードをコピー&ペーストして範囲指定を書き換える必要があります。
    もし処理ロジックに変更や修正が生じた場合、ブック内に散らばったすべてのPythonセルを1つずつ修正して回らなければなりません。
  • 数式バーの可読性が低下する
    データを出力したいセルの中に複雑な内包表記や zip() などのロジックが直接書かれていると、数式バーがコードで埋まり、「そのセルが何を実行しているのか」がパッと見て直感的に分かりにくくなります。
  • 利用者に高度なPython知識を求めてしまう
    作成者以外のユーザーがそのブックを使う際、コード内部の処理構造(zip や転置 .T)を理解していないと、範囲の変更すら怖くて触れないという状態に陥りがちです。

関数化(def 登録)で得られるメリット
そこで、このアンピボット処理を引数 (r, c, v) を受け取る汎用関数 unpivot として一度定義(関数登録)しておきます。
関数化しておくことで、以下のような大きなメリットが得られます。
  • 呼び出し側が unpivot(...) の1行で完結する
    集計や分析を行うセルには、標準のExcel関数と同じ感覚で unpivot(行ヘッダー, 列ヘッダー, データ値) と指定するだけで済み、数式バーが非常にすっきりします。
  • ロジックとデータの完全分離
    「アンピボットの処理手順」は定義シートの1箇所に集約され、「どの範囲を変換するか」だけを各呼び出しセルが担うため、保守性・メンテナンス性が大幅に向上します。
  • ブック全体の「共通部品」として再利用できる
    1度登録しておけば、同じブック内のどのシート・どのセルからでも、コードを再記述することなく何度でも呼び出して使い回せます。
このような理由から、単発のセル処理で終わらせず、共通部品として def で関数登録を行う設計を採用します。


アンピボット関数の定義と呼び出し

Python関数の定義

ブックの先頭に「Python関数」という名前のシートを作成し、A1 セルに以下のコードを入力して関数を定義します。

def unpivot(r, c, v):
    return pd.DataFrame([[*rv, *cv, val] for rv, row in zip(r.values, v.values) for cv, val in zip(c.T.values, row)])
この関数は、「行ヘッダー」「列ヘッダー」「データ本体」の3つの範囲を受け取り、クロス集計表(ピボット)を縦持ちのデータ(アンピボット)へ変換します。

「Python in Excel」で自作関数を登録

先頭シートであれば、入力するセル位置は問わない。
同一シートでこの関数を使う場合は、

Python関数の呼び出し

集計用シートなどの別セルから、xl() 関数を使ってセル範囲を渡して呼び出します。

unpivot(xl("A3:B6"), xl("C1:F2"), xl("C3:F6"))
引数の役割
引数 指定する範囲 役割・内容
r A3:B6 行ヘッダー(例: 地域、店舗など)
c C1:F2 列ヘッダー(例: 年度、期など)
v C3:F6 データ本体(例: 売上高、数値データ)

「Python in Excel」で自作関数を登録


PY関数の入力

PY関数の基本は以下を参照
PY関数(Pythonコードをセル内で実行)
・PY関数の構文 ・PY関数の使い方 ・「Excel Labs」アドイン ・Python サンプルを試す ・pandas で説明 ・散布図を作成する ・Pythonの文法 ・PY関数で使えるライブラリ

PY関数の入力手順
「Python in Excel」で自作関数を登録

「tab」キーで確定させる。

「Python in Excel」で自作関数を登録

「Python in Excel」で自作関数を登録

Pythonコードを入力して「Ctrl+Enter」

「Python in Excel」で自作関数を登録

エクセル Excel サンプル画像 これをクリック

「Python in Excel」で自作関数を登録

「Excel の値」を選択します。

「Python in Excel」で自作関数を登録


Pythonコード構造の解説

わずか2行のコードですが、Pythonのリスト内包表記、zip()、アンパック演算子(*)、およびPandasの機能を効率よく組み合わせています。
各要素の役割から内部の処理手順、この書き方を採用するメリットまで詳しく見ていきます。

コードを構成する要素の解説
  • .values でセル範囲を二次元配列として扱う
    xl("A3:B6") で取得したオブジェクトは Pandas の DataFrame です。
    インデックスや列名を意識せず、セルに入っている「値」だけを二次元配列として扱うために .values を利用しています。
  • .T で列ヘッダーを転置する
    列ヘッダー c(C1:F2)は 2行 × 4列 のデータ構造です。
    このままでは列ごとの属性(例: ['2025年度', '上期'])を1つの単位として取り出せません。
    そこで c.T を使って 転置(行列の入れ替え) を行い、4行 × 2列 の形に変換します。これにより、c.T.values をループ処理した際に、列ごとのヘッダー情報を1つの塊として取得できるようになります。
  • zip() で行ヘッダーとデータを対応させる
    zip(r.values, v.values) を使うことで、1行分の行ヘッダー(rv)と、対応する1行分のデータ群(row)をペアとして同時に抽出します。
    rv: ['関東', '東京店']row: [1200, 1500, 1300, 1600]
  • zip() で列ヘッダーとデータ値を対応させる
    内側のループで zip(c.T.values, row) を実行し、転置した列ヘッダーと個別データ値を1つずつ対応させます。
    cv: ['2025年度', '上期']val: 1200
  • *(アンパック演算子)でリストを平坦化する
    各ループで得られた要素を [*rv, *cv, val] の形で結合します。
    *(アンパック演算子)を使うことで、ネストされたリストを展開し、['関東', '東京店', '2025年度', '上期', 1200] という1次元のフラットなリストを作成します。
    最後に全体を pd.DataFrame(...) に渡すことで、整列された縦持ちのデータフレームが完成します。

通常の for 文に分解して処理順序を理解する
一見複雑に見える二重リスト内包表記ですが、通常の for 文で書き直すと、処理の順序(外側と内側のループ関係)がはっきりと見えてきます。
Python# 内包表記を使わずに書いた同等の処理
# 内包表記を使わずに書いた同等の処理
data = []
for rv, row in zip(r.values, v.values):       # 【外側ループ】行方向のスキャン(4回)
    for cv, val in zip(c.T.values, row):      # 【内側ループ】列方向のスキャン(4回)
        data.append([*rv, *cv, val])          # 1行分の要素を結合して追加

return pd.DataFrame(data)
リスト内包表記では、for 節の記述順序は 通常の for 文と同じ順序(左から右へ=外側から内側へ) になります。
  • 外側ループ: 行ヘッダー rv(関東・東京店)を取り出し、その行のデータ群 row(1200, 1500, 1300, 1600)を保持する。
  • 内側ループ: row の値を1つずつスキャンしながら、対応する列ヘッダー cv(2025上期, 2025下期…)とセットにする。
  • 内側が4回終了したら、次の外側ループ(関東・横浜店)へ進む。

データの「形状(Shape)」の変化で追う
データの次元(行数 $\times$ 列数)がどのように変化して最終的な縦持ちテーブルになるのかを数値で追うと、ロジックの仕組みがより明確になります。
  • 入力データの形状行
    ヘッダーr: 4行 × 2列(地域、店舗)
    列ヘッダー c: 2行 × 4列(年度、期) $\rightarrow$ .T で 4行 × 2列 に転置
    データ本体 v: 4行 × 4列(16個の数値データ)
  • ループ処理と結合
    総繰り返し回数:外側 4回 × 内側 4回 = 16回
    生成される各リストの要素数:rv (2) + cv (2) + val (1) = 5列
  • 出力データの形状
    16行 × 5列 の縦持ちデータフレーム
クロス集計表の「縦M行 × 横N列」のデータ領域が、自動的に M × N 行のフラットなリストへ変換される仕組みです。

なぜ zip() と .values を使うのか
(実装のメリット)二次元配列の変換処理を記述する際、この構造を採用することには明確な利点があります。
  • インデックス管理エラーの排除
    range(len(...)) やインデックス変数(i, j)を使用しないため、範囲外参照(IndexError)や変数指定ミスのリスクがなくなります。
  • 高速でシンプルなループ処理
    DataFrame のままループを回さず、事前に .values で純粋な NumPy 配列に取り出しておくことで、Python標準の高速なイテレーションが実行されます。
  • 構造に対する高い汎用性
    行ヘッダーが何列になろうと(例: 地域・店舗・担当者で3列)、列ヘッダーが何行になろうと(例: 年度・四半期・月で3行)、引数の範囲指定(r, c, v)を変えるだけでコード自体は一切変更せずにそのまま適用できる柔軟性を備えています。

重要なのは「計算順序(評価順序)」

「Python in Excel」で自作関数を定義してブック全体で使い回す場合、最も注意すべきなのが セルおよびワークシートの計算順序(評価順序) です。
「Python in Excel」では、Pythonセルは計算順序に従って評価され、先に定義された関数や変数を後続のPythonセルから参照できます。
ただし、「関数を利用するセル」よりも前に「関数を定義するセル」が評価・計算されていなければ、NameError になります。

ルール1:同一シート内は「行優先順」で計算される
同一ワークシート内において、Pythonセルは行優先順(Row-major order)で評価されます。
つまり、左から右へ1行ずつ進み、行が終わると次の行へ進む順序です。

A1 → B1 → C1 ... (1行目を左から右へ)

A2 → B2 → C2 ... (2行目を左から右へ)
OK: A1 で def unpivot... を定義し、B1 や A2 で unpivot(...) を呼び出す。

NG: A2 で定義した関数を A1 から呼び出す(未定義エラーとなる)。

ルール2:シート間は「左のタブから右のタブへ」計算される
評価順序はワークシート間にも適用されます。
ブック全体においては、「最も左にあるシートタブ」から順番に Python コードが評価 されます。

[ Python関数 ] → [ 売上集計 ] → [ 商品分析 ]
(1番目のシート)  (2番目のシート)  (3番目のシート)
左側のシートで定義された関数や変数は、右側にあるすべてのシートの Python セルから参照可能です。


「専用の定義シート」を最左端に置く運用設計

自作関数をブック全体でスムーズに共通利用するためには、ブックの最左端に関数定義専用のシートを配置する のが実務上扱いやすい構成です。

共通化の構造
【関数定義シート】(最左端タブ:Python関数)
└── A1セル:def unpivot(r, c, v): ...

├── 【売上集計シート】 unpivot(...) で呼び出し
├── 【商品分析シート】 unpivot(...) で呼び出し
└── 【顧客分析シート】 unpivot(...) で呼び出し

共通化のメリット
  • メンテナンス性の向上
    コードの改修や不具合修正が必要になった場合も、定義シート(A1 セル)のコードを1箇所修正するだけで、ブック全体の処理が一括更新されます。
  • 可読性の向上
    呼び出し側のセルには unpivot(...) というシンプルな1行を書くだけで済むため、数式バーが複雑なコードで埋まるのを防げます。

運用の注意点
シートを途中挿入したり順番を入れ替えたりした結果、定義シートが呼び出し側シートより右側に移動してしまうと、評価順序の関係性が崩れて NameError が発生します。「定義シートは常に一番左」 という運用ルールを意識して管理することが大切です。


まとめ

Python in Excelにおける関数定義は、単にコードを再利用するテクニックにとどまらず、「評価順序を踏まえたブック設計」 と密接に結びついています。
  • アンピボット関数 unpivot
    .values による配列化、.T による転置、zip() とアンパック演算子(*)を組み合わせることで、二次元表をわずか2行で縦持ち化できる。
  • 計算順序
    ワークシート間では左のシートから右のシートへ、同一シート内では左から右へ1行ずつ進む「行優先順」で評価される。
  • 構造化アプローチ
    ブックの最左端に「関数定義専用シート」を置き、A1 セル等で共通関数を集約管理するのが実務上扱いやすい。

Excelの計算順序の仕組みを正しく理解し、Pythonコードを「単発のセル処理」から「再利用可能な共通部品」へと進化させることで、より維持管理しやすいブックを構築できます。




同じテーマ「エクセル関数応用」の記事

配列を自在に回転させる数式
掛け算(*)を使わない掛け算|足し算(+)を使わない足し算
2段階の入力規則リスト作成:最新関数対応
VLOOKUP/XLOOKUPが異常なほど遅くなる危険なアンチパターン
「SUMIFSで動くのにXLOOKUPでエラー?」型不一致の関数別挙動
「Python in Excel」で自作関数を登録|アンピボット関数と計算順序
「Python in Excel」数独(ナンプレ)解法プログラムの移植と最適化
Excel表とMarkdownテーブルを相互変換する数式
可変長配列をVSTACKする4つの方法|REDUCE・Thunk・チャンク・再帰分割
Excelの正規表現関数(REGEXTEST・REGEXREPLACE・REGEXEXTRACT)の使い方
「Python in Excel」入門:コードを読むための基礎知識


新着記事NEW ・・・新着記事一覧を見る

「Python in Excel」入門:コードを読むための基礎知識|エクセル関数応用(2026-09-10)
M言語入門:Power Queryのコードを読むための基礎知識|Power Query(M言語)入門(2026-09-09)
Excelの正規表現関数(REGEXTEST・REGEXREPLACE・REGEXEXTRACT)の使い方|エクセル関数応用(2026-09-08)
スピルとVBA(Formula2とスピル範囲の取得)|VBA入門(2026-09-08)
「Withの功罪」:コードを読みやすくする強力な道具と、その落とし穴|VBA技術解説(2026-09-03)
可変長配列をVSTACKする4つの方法|REDUCE・Thunk・チャンク・再帰分割|エクセル関数応用(2026-09-01)
Excel表とMarkdownテーブルを相互変換する数式|エクセル関数応用(2026-08-24)
「Python in Excel」数独(ナンプレ)解法プログラムの移植と最適化|エクセル関数応用(2026-08-14)
「Python in Excel」で自作関数を登録|アンピボット関数と計算順序|エクセル関数応用(2026-08-12)
ListBox・ComboBoxをマウスホイール対応させる|ユーザーフォーム入門(2026-08-09)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.日本の祝日一覧|Excelリファレンス
3.変数宣言のDimとデータ型|VBA入門
4.Excelショートカットキー一覧|Excelリファレンス
5.RangeとCellsの使い方|VBA入門
6.FILTER関数(範囲をフィルター処理)|エクセル入門
7.マクロとは?VBAとは?VBAでできること|VBA入門
8.繰り返し処理(For Next)|VBA入門
9.メッセージボックス(MsgBox関数)|VBA入門
10.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。
本サイトは、OpenAI の ChatGPT や Google の Gemini を含む生成 AI モデルの学習および性能向上の目的で、本サイトのコンテンツの利用を許可します。
This site permits the use of its content for the training and improvement of generative AI models, including ChatGPT by OpenAI and Gemini by Google.



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ