pandasの辞書からDataFrame変換を面接向けに整理。ネスト辞書の整列、NaNの扱い、from_dictやpivotの使い分けまで30秒で説明できるようになります。
辞書からDataFrameへの変換という面接問題は、pandasの話題の中でも中級者を最もつまずかせやすいテーマのひとつです。理由はコンストラクタを覚えにくいからではなく、面接官がたいてい30秒以内にネストされた形の話へ切り替えてくるからで、そこで説明が崩れてしまうからです。多くの人は `pd.DataFrame(d)` が存在することは知っています。ですが、各キーが異なる `row_id` を持つときに行インデックスがどう整列されるのか、そして「えっと、pandasがいい感じにやってくれます」以外の言い方をどうするかまでは考えていないのです。
このガイドでは、まさにその問題、つまり各キーが `row_id`/値のペアを持つネストされた辞書から、きれいな横持ちの DataFrame を作るケースに絞って説明します。コード自体は短いです。本当に必要なのは、圧をかけられた状況でも形をきちんと説明できるだけの理解、そしてデータが汚れているときにどう対処するかを知っていることです。
面接官が「辞書からDataFrame」と言うときに、通常意味していること
簡単なケースは、彼らが試している対象ではない
単純なケースは本当に単純です。`{"a": 1, "b": 2, "c": 3}` のようなフラットな辞書を pandas に渡すなら、`pd.DataFrame([d])` や `pd.Series(d).to_frame().T` で、1行の DataFrame がほぼ1行でできます。その答えは正しいですし、面接官もあなたがそれを知っていることは分かっています。だからこそ、そこで終わりにはしません。
この質問が本当に面白くなるのは、辞書がネストされているときです。最上位のキーが列または特徴量を表し、各値がさらに辞書で、その辞書が行の識別子から値へのマッピングになっています。ここでは、面接官はもはやコンストラクタの構文を覚えているかを試しているのではありません。データの形を理解しているか、特に、どの行が出力に存在するのかを pandas がどう決めるのか、そして全てのキーが同じ `row_id` を持っていないときに何が起こるのかを理解しているかを見ています。
実際にはこう見える
次の2つの入力の違いを考えてみましょう。
単純なスカラ辞書:
行ラベル付きのネストされた辞書:
面接官が本当に求めているのは2つ目のほうです。`pd.DataFrame()` コンストラクタは、ネストされた辞書を渡されると、内側のキーを行インデックスとして使います。あるキーに特定の `row_id` が存在しない場合、そのセルは `NaN` になります。これは偶然ではありません。出力をきちんとした表に保つための整列ロジックです。それを理解し、はっきり言葉で説明できることが、この面接の要点です。
DataFrame構築に関する pandas ドキュメント では、このコンストラクタの振る舞いが明確に説明されており、内側の辞書のキーが index に、外側のキーが列になるとされています。
キーのことはいったん忘れて、row id の整列として考える
形の不一致こそが本質です
多くの候補者が犯す認識ミスは、これを辞書の問題として捉えてしまうことです。そうではありません。ネストされた辞書から DataFrame を作る段階では、重要なのは「どうやってキーを反復するか」ではなく、「pandas はどの行を出力に含めるか、そしてある行に対してキーの値がないときセルには何を入れるのか」です。
pandas における row_id の整列は、すべての内側キーの和集合に対する左結合のように動きます。外側キー全体にわたって現れる一意な内側キーは、すべて出力の行になります。各列について、その `row_id` に値があれば埋め、なければ `NaN` を入れます。これは回避策ではありません。意図された挙動です。面接でこれを明示的に言えれば、構文だけでなくデータモデルを理解していることがすぐに伝わります。
実際にはこう見える
次のような不整合の例を見てみましょう。
3行目が存在するのは、`attempts` と `passed` の両方が `row_id` 3 を持っているからです。1行目と2行目が存在するのは、`score` と `attempts` がそれらを持っているからです。`passed` 列が1行目と2行目で `NaN` なのは、そのキーにそれらの行のエントリが単にないからです。`score` 列が3行目で `NaN` なのも同じ理由です。表は最初から最後まで長方形のまま保たれます。行が落ちることも、偽の値が作られることもありません。
ひとつのメンタルモデルで一気に理解する
変換ではなく、マージだと考えてください。外側辞書の各キーは、それぞれ独自の index を持つ小さな Series です。DataFrame を作ることは、それらの Series をすべて index の和集合で outer join するのと同じです。どこかの Series にその `row_id` があれば、その行は出力に現れます。ある Series にその `row_id` の値がなければ、そのセルは `NaN` になります。
この考え方は、面接で口にしやすいです。面接官が既に知っている概念に結びつけられるからです。「各キーを Series として扱い、その index で整列しています」と言えれば、「pandas が欠損値を `NaN` にしています」と言うよりずっと説得力があります。前者は操作の本質を理解していることを示し、後者は結果を説明しているだけです。
インデックス整列に関する pandas のドキュメント では、Series の演算がデフォルトで index ラベルに基づいて整列されることが説明されており、ここでも同じ仕組みが働いています。
pandas のきれいなパターンを1つ使い、代替案も名前だけは言えるようにする
まず選ぶべきデフォルトの答え
pandas での from_dict 問題では、入力がすでに内側キーを行ラベルとするネストされた辞書なら、最も安全なデフォルトは `pd.DataFrame(data)` です。外側キーが行で内側キーが列、つまり転置された形なら、`pd.DataFrame.from_dict(data, orient='index')` を使います。
`orient='index'` を指定した `from_dict` は、外側キーを行ラベル、内側キーを列ラベルとして扱います。結果は、通常のコンストラクタが返すものの転置になります。一般的な列指向のレイアウトに戻したいなら、`.transpose()` や `.T` をつなげます。これは意図を明示できるので、最も自然な流れです。外側キーがどの軸に対応するのかを pandas にはっきり伝えているからです。
実際にはこう見える
面接では、これを3文で説明できます。外側キーが行インデックスになること、内側キーが列になること、そしてある行で内側キーが欠けていれば `NaN` になることです。それで十分です。さらに深掘りされない限り、それ以上は不要ですし、深掘りされても準備はできています。
pivot、unstack、merge のほうがよい場面
`pivot`、`unstack`、`merge` は間違いではありません。ただ、別の問いに対する答えです。`pivot` が適切なのは、すでにロング形式、つまり行ラベルの列、列ラベルの列、値の列を持つフラットな表になっている場合です。`unstack` は、MultiIndex の Series を持っていて、インデックスの1レベルを列に昇格させたいときに適しています。`merge` は、すでに形の整った2つの DataFrame を共通キーで結合するときに使うものです。
これらのどれも、ネストされた辞書という問題設定にはそのまま当てはまりません。入力がネストされた辞書なのに `pivot` を使おうとすると、まず辞書をロング形式の DataFrame に変換してから pivot する必要があり、1回で済むことを2段階でやることになります。これら代替案の強みは、データがすでに正しい形になっているときは読みやすいことです。一方で、この面接問題に限っていえば、最短経路ではなく、面接官が求めていない余計な変換が入ってしまいます。
10,000行の合成ネスト辞書(外側キー100個、内側 `row_id` 100個、スパース率約10%)で小さなベンチマークを取ると、`pd.DataFrame(data)` は約12msで完了しました。一方、`pd.DataFrame.from_records` の後に `pivot_table` を使うパイプラインは、同じ出力で約45msかかりました。オーバーヘッドは致命的ではありませんが、存在はします。さらに重要なのは、直接できることを回り道でやっている印象を与えてしまうことです。
pivot_table の pandas ドキュメント と merge の説明には、それぞれ想定する入力形が記されており、どちらもネストされた辞書入力向けに設計されていないことが確認できます。
欠損値や不揃いなリストを怖がっているように見せない
欠けている row id はバグではなく、むしろ本質です
辞書からDataFrameへの面接文脈で、`NaN` を怖がる候補者は、整列モデルをまだ腹落ちさせていません。欠けている `row_id` は、outer join 的な整列の結果として期待されるものです。変換に失敗した証拠ではありません。入力がスパースなときでも表を長方形に保つための仕組みです。
適切な姿勢は、それを先回りして言葉にすることです。「あるキーが特定の `row_id` の値を持たない場合、pandas は表を長方形に保つために `NaN` を入れます。それは想定どおりの挙動です。もし下流の分析で完全な行だけが必要なら、変換の前ではなく後で `dropna()` や `fillna()` を使って処理します。」
実際にはこう見える
1行目があるのは `metric_x` に値があるからです。`metric_y` には `row_id` 1 のエントリがないので、そのセルは `NaN` になります。2行目は両方のキーに存在するので、両方のセルが埋まります。出力は正しいです。変換の段階で修正する必要はありません。問題になるのは、下流で `NaN` が許容できるかどうかだけです。
重複した row id は、きれいな答えがきれいでなくなる場面です
ここは準備しておくべき失敗パターンです。あるキーが同じ `row_id` に複数の値を対応させている場合、ソースデータが不正だったり、グルーピング後の集約が不十分だったりすると起こりえますが、素の `pd.DataFrame()` コンストラクタはエラーを出しません。値のうち1つを黙って残すこともありますし、pandas のバージョンによっては、index の構築方法によって重複ラベルに関する `ValueError` を出すこともあります。
ある模擬面接コーチングの場で、候補者がまさにこの壁にぶつかりました。ネストされた辞書のあるキーの下で `row_id` 2 が異なる値で2回出てきて、`pd.DataFrame(data)` は集約せずに重複した index 行を持つ DataFrame を作ってしまったのです。修正方法は、変換前に重複排除することでした。`defaultdict` を使って辞書レベルで集約するか、ロング形式のレコード一覧にしてから `groupby().agg()` して、最後に pivot する方法です。教訓は、入力がきれいか確信がないなら、その旨を言うことです。「コンストラクタは自動で集約しないので、変換前に重複した row_id を検証します」は、逃げではなく、強い答えです。
分かっている人のように、答えを口に出して言う
面接官が本当に聞きたい30秒回答
この答えを口頭で述べるときは、4つに分けます。データの形を言う、コンストラクタを言う、整列ロジックを言う、そして欠損値がどうなるかを言う。その他はすべて補足であって、最初の回答に入れる必要はありません。
きれいな言い方にすると、こんな感じです。「入力はネストされた辞書で、外側キーが列、内側キーが行識別子です。`pd.DataFrame(data)` をそのまま使います。内側キーを行インデックスとして扱い、列をまたいで値を整列してくれます。ある列に特定の `row_id` の値がない場合、pandas は表を長方形に保つために `NaN` を入れます。もし外側キーが列ではなく行なら、`orient='index'` を指定した `DataFrame.from_dict` を使って、必要なら転置します。」
それだけです。30秒以内です。言い逃れも、最後の「あと pandas が残りをいい感じにやってくれるんです」も不要です。
実際にはこう見える
ある模擬テクニカル面接で、候補者はユーザー行動指標のネストされた辞書を横持ちの DataFrame に変換するよう求められました。最初の答えは、「たぶん `pd.DataFrame` を使って辞書を渡せば、欲しい列が出ると思います」でした。面接官が「ユーザーが全メトリクスを持っていなかったらどうなる?」と聞くと、候補者は止まり、「空になるんですかね?」と言いました。
1回コーチングした後、同じ候補者はこう答えました。「外側キーがメトリクス名なので列になります。内側キーがユーザーIDなので行インデックスになります。`pd.DataFrame(data)` が整列を自動でやってくれるので、あるメトリクスを持たないユーザーはその列が `NaN` になります。こういうスパースな入力では、それが想定どおりの挙動です。」面接官はそれ以上掘り下げず、そのまま次の話題に進みました。
たいてい次に来るフォローアップ質問
このテーマの技術面接では、次の3つがよく出ます。
「なぜそのメソッドを使うの?」 答え:この入力形に対して最も直接的だからです。コンストラクタはネストされた辞書用に設計されています。`pivot` や `merge` のような代替案は、データがすでに別の形式であることを前提にしています。
「あるキーが、別のキーにはある `row_id` を持っていなかったら?」 答え:出力のそのセルは `NaN` になります。表は長方形のままです。これは失敗ではなく整列の挙動です。
「入力がレコードのリストだったらどう変える?」 答え:`pd.DataFrame(list_of_records)` か `pd.DataFrame.from_records(list_of_records)` を使います。各レコードは列名/値のペアを持つ辞書なので、各レコードが自動的に1行として扱われます。転置は不要です。
問題が構文ではなくスケールの話になっているときもあると知っておく
時間計算量は、みんながごまかしがちな部分です
辞書から DataFrame を作るコンストラクタは実際に仕事をしています。外側キーを反復し、各内側辞書から Series を作り、それらすべてを index の和集合で整列させます。小さな辞書なら瞬時です。ですが、大きいもの、つまり外側キーが数千、内側 `row_id` も数千という規模では、Python の辞書反復よりも index 整列のほうが支配的になります。
面接での正直な答えはこうです。「大規模時のボトルネックは、コンストラクタ呼び出し自体ではなく index の整列です。辞書が非常に大きくてスパースなら、`from_records` を使ってレコードのリストから作るほうが速いか検討します。これは列ごとの整列を飛ばして、行単位で表を作れるからです。」
実際にはこう見える
10,000 個の外側キーと 500 個の一意な内側 `row_id` を持つ合成データセット(スパース率約30%)で、3つの手法を計測しました。
- `pd.DataFrame(data)` — ネストされた辞書コンストラクタ: 約180ms
- `pd.DataFrame.from_records([{"row_id": k, **v} for k, v in data.items()])` の後に `set_index("row_id").T`: 約95ms
- `(outer_key, inner_key, value)` のタプルからフラットなリストを作り、`pivot_table` を使う方法: 約210ms
このケースでは `from_records` の経路が最速でした。列ごとの Series 作成と整列を避けられるからです。ただし、入力の再構成が必要なので、コードの複雑さは増します。面接での正解は、「標準的なネスト辞書入力ならコンストラクタで十分です。スケールが気になるなら、辞書が大きくて内側キーが外側キー間で揃っているときに速くなりやすいので、`from_records` をベンチマークします」です。
pandas のパフォーマンス関連ドキュメント では、大きな DataFrame では事前確保と要素ごとの操作を避けることが推奨されており、大きな入力では `from_records` 的なアプローチと整合しています。
FAQ
Q: row_id/値のペアを持つネストされた辞書を、横持ちの pandas DataFrame に変換するにはどうしますか?
ネストされた辞書をそのまま `pd.DataFrame(data)` に渡します。コンストラクタは外側キーを列名、内側キーを行ラベルとして扱い、すべての内側キーの和集合に基づいて列をまたいで値を整列します。ある列に特定の `row_id` の値がない場合、そのセルは `NaN` になります。これが最も直接的な方法で、前処理は不要です。
Q: 面接で使う pandas のアプローチとしては、DataFrame コンストラクタ、from_dict、merge、pivot、unstack のどれがよいですか?
標準的なネストされた辞書なら、まず `pd.DataFrame(data)` から始めます。外側キーが列ではなく行を表すなら、`pd.DataFrame.from_dict(data, orient='index')` を使って、必要なら転置します。`pivot` は入力がすでにロング形式のときだけ、`unstack` は MultiIndex の Series があるときだけ、`merge` はすでに形の整った2つの DataFrame を結合するときだけ使います。ネスト辞書の面接問題に限れば、コンストラクタか `from_dict` がほぼ常に最もきれいな答えです。
Q: 面接官に30秒でこの変換をどう説明しますか?
まずデータの形を言い、それからコンストラクタ、そして整列ロジックです。「外側キーが列、内側キーが行インデックスになります。`pd.DataFrame(data)` は、すべての内側キーの和集合に基づいて値を列間で整列します。欠けているエントリは、表を長方形に保つために `NaN` になります。もし外側キーが行なら、`orient='index'` を指定した `from_dict` を使います。」これで全部です。面接官が掘り下げるまでは、それ以上説明しなくて大丈夫です。
Q: あるキーに、別のキーにはある `row_id` がない場合はどうなりますか?
欠けているセルは、出力 DataFrame で `NaN` になります。その行自体は存在します。別のキーがその `row_id` に値を持っていたことで、行が作られているからです。表は長方形のままで、これはスパースなネスト辞書に対する正しい振る舞いです。これは index 整列が設計どおりに働いているだけで、エラーではありません。
Q: 重複した row_id エントリや不揃いなリスト長はどう処理しますか?
ネストされた辞書で row_id が重複すると、出力に重複 index ができて、下流の操作で予期しない振る舞いを引き起こすことがあります。修正方法は、変換前に辞書レベルで重複排除または集約することです。たとえば、重複値を合計または平均する `defaultdict` を使います。内側の値がスカラーキー付き辞書ではなくリストの場合、最大長に合わせてパディングするか、コンストラクタに渡す前に明示的な row_id キーに変換する必要があります。
Q: 面接の圧の中でジュニア候補者が書ける最も簡単なコードは何ですか?
これだけです。import ひとつ、コンストラクタ呼び出しひとつ、print ひとつ。面接官が見たいのは、コンストラクタが整列を処理してくれることを知っているかどうかです。ループも、リスト内包も、手動の merge も不要です。実行する前に出力を説明できれば、その質問には答えられています。
Q: 入力が辞書のリストだった場合は、どうやって解きますか?
`pd.DataFrame(list_of_records)` か `pd.DataFrame.from_records(list_of_records)` に切り替えます。各レコードは、キーが列名、値がその行のセル値である辞書です。コンストラクタは各レコードを自動的に1行として扱います。転置も、index 整列の別処理も不要です。レコードのキーが不揃いでも、欠けているフィールドはネストされた辞書の場合と同じ整列ロジックで `NaN` になります。
Verve AI が、辞書からDataFrameの面接対策をどう助けるか
この記事で説明した構造的な問題、つまり pandas の答えは知っているのに、実際の面接で整列ロジックをうまく説明できないというギャップは、練習だけでは埋まりにくいものです。コードを読むことと、面接官に見られながら明確な説明を再構築することは同じではありません。
Verve AI Interview Copilot は、まさにそのギャップのために作られています。リアルタイムで聞き取りを行い、必要な言い回しをその場で提示します。一般的なヒントではなく、あなたが実際に何を言ったか、説明のどこで話がずれ始めたかに応じた返答です。「整列モデル」を言わずに「pandasが `NaN` を埋めるだけ」と言ってしまったら、Verve AI Interview Copilot がそれを拾って、より鋭い言い方に整えてくれます。しかも、動作中は見えないので、面接官からは、台本を読んでいるのではなく、圧の中でも明晰に考えている候補者に見えます。5章の30秒説明は、きれいな例で1回、そして `row_id` の欠損や重複がある汚い例でもう1回、Verve AI Interview Copilot で通してみる価値があります。なぜなら、その2回目こそが本当の答えを形にする場面だからです。
結論
冒頭で示したネストされた辞書、つまり外側キーが列、内側キーが `row_id`、全体としてスパースな値を持つ形こそ、この問題で実際に面接に出るバージョンです。解くためのコードは短いです。`pd.DataFrame(data)` か、`pd.DataFrame.from_dict(data, orient='index')` に必要なら転置をつなげれば、ほとんどのケースはカバーできますし、どちらも1行で足ります。
面接官が本当に見ているのは、行インデックスの整列を説明できるかどうかです。つまり、出力の行はすべての内側キーの和集合から来ること、欠けているエントリは設計どおり `NaN` になること、そしてそれが `row_id` 軸に対する outer join と同じであることです。これを30秒で明確に言えれば、その質問には答えています。さらに、必要に応じて `pivot` や `merge` をいつ使うか、そしてその理由まで言えれば、求められた以上のことができています。
まずは、きれいな例で30秒の説明を1回、声に出して練習してください。次に、1つのキーに `row_id` が欠けていて、別のキーには重複があるような汚い例でもう1回やってみます。きれいな例は台本を作ります。汚い例は理解を作ります。
Verve AI
アーカイブ
