pandasのconcatで縦に結合したら列がずれてNaNだらけになった原因と対処法を試した話

業務でPythonを使い始めたばかりの頃のことです。私はデータの結合という壁にぶつかりました。毎月の売上データを一つの大きな表にまとめようとしました。二つのCSVファイルを読み込み、結合を試みます。「さあ結合だ」と意気揚々とコードを実行したのです。ところが、画面に表示された結果を見て私は言葉を失いました。本来なら縦にきれいに並ぶはずのデータです。それがなぜか横に広がってしまったのです。しかも、表のあちこちに「NaN」という見慣れない文字が並びます。元のデータの倍以上の列数になっていました。

実は、この失敗にはpandas特有の仕組みが関係しています。「列名による自動補正」という機能のことです。非エンジニアの私にとって、プログラミングは魔法のツールでした。一瞬で作業を終わらせてくれるものに見えていたのです。しかし、実際にはコンピュータの厳密なルール理解が不可欠です。それを知らないと、かえって手間が増えてしまうこともあります。今回は、私が実務で体験した「pd.concatによる列ずれ事件」を扱います。その原因と、解決のために試行した四つの対処法を詳しく共有しましょう。

データ結合、まさかの横増殖

月次のレポート作成は、事務職にとって最も神経を使う仕事です。私は以前、先月分と今月分の売上データを統合しようと試みました。Pythonを使ってこの集計作業を自動化したかったのです。それぞれのCSVファイルは、一見すると全く同じに見えました。項目名も並び順も同じだと思ったのです。そのため、pandasのconcat関数を使えば簡単だと信じていました。単純に上から下へ積み重なるものだと疑いませんでした。しかし、実行後のデータフレームを表示した瞬間のことです。私は思わず椅子から転げ落ちそうになりました。

データ横増殖、修正に数時間

そこには、異様な表が広がっていました。縦に伸びるはずのデータが不自然に横へと増殖していたのです。例えば、本来なら「商品名」という一つの列に収まるはずのデータです。それがなぜか二つの異なる列に分かれて配置されていました。しかも、片方のデータがある行ではもう片方が空欄になります。逆もまた然りというひどい状態でした。まさにパズルがバラバラに組み合わさったような無残な形です。私はこの惨状を目の当たりにしました。自分の書いたコードのどこに間違いがあったのか分かりません。

月次報告の締め切りが数時間後に迫る中、焦って画面を見つめても、どこを直せばいいのか分かりません。本当は5分で終わらせたかった作業に、結局その日は数時間かかってしまいました。

データ結合の惨劇:NaNと幽霊列の猛威

データが結合された表はひどい有様でした。「NaN」という文字がいたるところに並んでいました。このNaNとは、プログラミングの世界で使う特別な記号です。「データが存在しないこと」を指しています。本来なら数字や文字列が入っているべき場所です。そこにこの無機質な三文字が並んでいる光景は恐ろしいものです。非エンジニアにとっては非常に恐怖を感じます。特に、合計金額を算出しようとした時に困りました。NaNが含まれているせいで計算エラーが発生したのです。集計作業が全く進まなくなってしまいました。

結合で増殖する幽霊列とデータ混乱

さらに厄介なことに、列の総数が勝手に増えていました。元のCSVが10列だったのに、結合後は15列になっています。増えた列の正体を確認してみました。元の列名と微妙に違う名前が付けられた幽霊のような列です。これでは、どのデータが正解なのか判断がつきません。なぜ単純な縦の結合でこのような不具合が起きるのでしょうか。私にはその理由が全く理解できませんでした。一つ一つのセルを確認する作業は、膨大な時間を奪います。私の視力と精神をどんどん削っていきました。

pandasのデータフレームを表示した画面。多くのセルが「NaN」で埋め尽くされ

ここで一度立ち止まって考えてみてください

Pythonや自動化スキルを体系的に習得して、ITエンジニアとしてのキャリアを切り開きたい方には「Enjoy Tech!(エンジョイテック)」が選択肢のひとつです。現役エンジニアのサポートで、未経験から実践的なスキルを身につけられます。

プログラミングスクール Enjoy Tech!(エンジョイテック) →

NaNの正体:pd.concatの列名不一致

必死に調べていくうちに、ようやく原因が判明しました。実は、pandasのpd.concat関数には特徴があります。データを結合する際に「列名」を厳密にチェックしているのです。私たちは人間なので、直感的に同じ意味だろうと判断します。「項目が同じ場所にあるから大丈夫」と思ってしまいます。しかし、プログラムの処理は全く異なるものでした。プログラムにとって縦結合は単に「下に置く」ことではありません。「同じ名前の列を探して、その下にデータを配置する」作業です。

つまり、列名が少しでも異なれば別の項目になります。pandasはそれを「全く別の項目」として認識するのです。その結果、新しい列を右側に作り出します。そしてデータが存在しない場所をNaNで埋めてしまいます。これが、列が横にズレてNaNだらけになる仕組みの正体でした。私はそれまで、データの並び順さえ合っていれば良いと思いました。しかし、それは大きな間違いだったのです。コンピュータは「名前の一致」に対して非常に潔癖でした。私たちが思っている以上の厳密さを持っていたのです。

本来なら10列で済むはずのデータが、結合後には15列に膨れ上がっていました。

たった1文字の落とし穴

それでは、なぜ私のCSVでは列名が違うと判定されたのでしょうか。調べてみると、信じられないほど些細な違いが原因でした。例えば、ある月のファイルでは「商品名」となっていました。別の月のファイルでは「商品名 」となっていたのです。末尾に全角スペースが一つだけ紛れ込んでいました。人間が見れば全く同じに見えます。しかしプログラムにとっては「A」と「B」くらい大きな違いです。完全に別のものとして認識されてしまいます。

他にも、半角と全角の違いなどが問題になります。項目の前後に含まれる目に見えない改行コードなども厄介です。これらは全て「別物」として扱われてしまいます。私のケースでは、出力元の違いでこの「表記ゆれ」が発生しました。経理システムから出力したデータと、手入力したデータの違いです。実は、この些細なスペース一つが私の数時間を奪った犯人でした。これを特定したとき、私はあまりの馬鹿馬鹿しさに脱力しました。しかし同時に、プログラムの厳密さを深く学ぶ良い機会となったのです。

二つのデータフレームの列名リストを比較している画面。片方の「商品名」の後に赤いハ

列名不一致、全角スペースの罠

列名の不一致を探すために、一文字ずつ画面をなぞって確認しました。見た目では全く同じなのに、別々の列になる理由が分かりません。ところが、print関数で列名の長さを出力してみると、一文字分だけ違うことが発覚したのです。原因が「たった一つの全角スペース」だと分かり、思わずため息が出ました。

列名上書きとstrip()処理

原因が分かれば、しっかりとした対策が立てられます。まず私が試した最も確実な方法は、力技のアプローチです。結合を行う直前に「列名を完全に統一する」という方法を選びました。具体的には、一方のデータフレームの列名を上書きしてしまいます。もう一方の列名でそのまま覆い被せるような形です。片方の列名一覧を、もう片方の列名一覧でそろえるイメージになります。この処理を結合コードの前に書き加えるだけです。これにより、目に見えないスペースや表記ゆれが強制的に解消されます。pandasは迷うことなくデータを縦に並べてくれるようになりました。

ただし、この方法には気をつけるべき注意点があります。元の列の順番が二つのデータで完全に一致していることが前提です。もし並び順が違う状態で列名を上書きしてしまうと危険です。データの意味が入れ替わってしまうという恐ろしい事態を招きます。そこで私は、名前を上書きする前に一手間加えることにしました。必ず「strip()」という関数を使うようにしたのです。列名の前後にある余計な空白を取り除く処理をルーチンに組み込みました。これにより、人為的なミスを最小限に抑えることに成功しました。

concat内部結合でデータ整理

次に行き着いたのは、concat関数のオプションを活用する方法です。デフォルトのconcatは「外部結合」という設定になっています。少しでも名前が違う列があれば全て残そうとする仕様です。これを「join=’inner’(内部結合)」に変更してみましょう。すると、二つのデータに共通している列名だけを抽出して結合します。表記ゆれがある余計な列は、自動的に切り捨てられる仕組みです。結合の段階で不要なデータを排除できるので非常に便利です。

実際にこの設定を試してみると、驚くほど結果が変わりました。画面に表示される表がスッキリと整理されたのです。NaNだらけの幽霊列が消え、必要なデータだけが整然と並びます。それを見て、私は心底安心しました。もちろん、大切な項目まで消えてしまわないよう注意は必要です。事前に共通の列がどれなのかをしっかり把握しておきましょう。しかし、一時的な計算や集計のために統合したい場合もあります。素早くデータをまとめたい時には、この内部結合がとても役立ちます。非常に強力な武器になると実感しました。

pd.concatの引数に join='inner' を指定して実行しているコー

インデックス重複解消は「ignore_index=Tr…

列名の問題が解決しても、次に私を悩ませたのが「インデックス」です。複数のデータを結合すると、元データの行番号がそのまま維持されます。インデックスが引き継がれてしまうのです。その結果、結合後の表に「0番」や「1番」の行が複数存在します。特定の行を指定して操作しようとするとエラーが発生することがありました。これを防ぐために、私はある便利なオプションを使い始めました。「ignore_index=True」という指定を追加したのです。

この一文を加えるだけで、結合後の行番号が綺麗に振り直されます。「0, 1, 2…」というように規則正しい連番になるのです。元の行番号に意味がない場合は、この設定をデフォルトで使っても良いくらいです。非常に便利なので重宝しています。実際に通し番号が整った表を見ると、安心感が増しました。データの整合性がきちんと取れていると感じられるからです。バラバラだった複数のCSVが一つの「新しいリスト」に生まれ変わりました。些細なことですが、後のデータ処理をスムーズにするためには欠かせません。非常に重要なステップだと思いました。

axis設定の罠、その確認と回避策

基本的なことかもしれませんが、初心者が陥りやすい罠があります。それは「axis(軸)」の設定ミスです。pd.concatは「axis=0」で縦に積む仕組みになっています。そして「axis=1」と書くと横に並べる処理になります。私は一度、疲れている時にこの数字を書き間違えてしまいました。本来縦に積みたかったデータを無理やり横に連結してしまったのです。その時も、大量のNaNが発生してしまいました。列名が重複するというカオスな状態に陥ったのです。

列名は合っているはずなのにデータが変な形に広がることがあります。その場合は、まずこの「axis」の設定を確認してください。強くお勧めします。デフォルトは「axis=0」なので、あえて書かなくても縦に積まれます。しかし、明示的に記述することで思わぬミスを防げるでしょう。私はこの失敗以来、コードを書くときは必ず自問自答するようになりました。「今は縦方向に操作しているのか」と毎回確認しています。単純な数字一つで結果が180度変わってしまいます。それがプログラミングの面白さでもあり、怖さでもあるのです。

Jupyter Notebook上で axis=0 と axis=1 の違いを解

データ結合の鍵は列名チェック

これらのトラブルを経て、私は一つの習慣を身につけました。結合を行う直前に、両方の列名を一覧で表示して見比べることです。それぞれのデータフレームの列名を並べて確認するようにしました。これをやるだけで、目に見える表記ゆれや順序の違いを事前に察知できます。たった数秒のわずかな手間です。しかし、この「事前の確認」を怠ると数時間の修正作業が発生します。それを考えれば、これほどコストパフォーマンスの良い作業はありません。

また、最近ではプログラムに列名の不一致を自動チェックさせています。そのために便利な短いコードを使うようにしました。もし一致しなければ、そこで処理を停止するように設定しています。こうしておけば、汚いデータが生成されるのを未然に防げます。非エンジニアにとって、プログラムを動かすこと自体がゴールになりがちです。しかし、本当に大切なのは「正しいデータが作られているか」の検証です。その大切さを、私は痛いほど思い知らされたのでした。

事前チェックでデータ不備と自信

結合前の列名チェックを自動化してから、データの不備を即座に発見できるようになりました。以前は結合後に「あれ、NaNが多いな」と後悔していました。今では実行前の警告メッセージを見て「ああ、また全角スペースが入っているな」と余裕を持って修正できます。おかげで日々の仕事に少しずつ自信が持てるようになりました。

データ結合のパズルピース

今回ご紹介した四つの対処法は、状況に応じて使い分けるのがベストです。まず、二つのデータの項目が本質的に同じである場合を考えます。その時は「対処1:列名の直接統一」が最もシンプルで効果的です。一方で、もし片方のデータに不要な列が多く含まれている場合もあります。そんな時は「対処2:内部結合」を使ってみてください。ゴミを取り除きつつ安全に統合できます。この二つの使い分けができるようになるだけで大きな進歩です。大半の列ずれ問題はこれだけで解消します。

次に、インデックスの重複が心配な場合についてです。「対処3:ignore_index=True」をセットで使うのが定石になります。そして、何をやっても解決しない時は基本に立ち返りましょう。「対処4:axisの確認」を行うようにしています。非エンジニアの私たちは、複雑なコードを書く必要はありません。こうした基本的なオプションの意味を理解することが重要です。自分の手元にあるデータの特徴に合わせてパズルのピースを選びます。それをうまく組み合わせることが大切です。それが、業務効率化を成功させるための現実的なアプローチだと考えています。

データ結合 失敗からの学び

pandasでデータを結合してNaNだらけになった時のことです。多くの人は「自分には向いていないのかも」と落ち込んでしまうかもしれません。でも、どうか安心してください。それは決してあなたが悪いのではありません。単にコンピュータの厳密なルールを知らなかっただけです。全角スペース一つでデータが壊れる世界は、確かに不便に感じることもあります。しかし、一度ルールを覚えてしまえば、これほど強力な味方はありません。

最初は誰でも失敗して当たり前です。私も、数え切れないほどのNaNを生成してきました。そのたびに深く頭を抱えて悩んだものです。しかし、その失敗があったからこそ学べたことがあります。データの構造を以前より深く理解できるようになりました。今回紹介した対処法を一つずつ試してみてください。必ずあなたのデータは綺麗に整うはずです。手作業でコピペを繰り返していた頃の自分を思い出します。「もう大丈夫だよ」と言ってあげられる日が、もうすぐそこまで来ています。私もまだ手探りですが、同じところで困っている人の役に立てばうれしいです。

以前は列ずれの後始末に1時間以上かかっていましたが、今は結合前の列名チェックが1分ほどで済むようになりました。

無料プレゼント

Excel業務を自動化する前に確認するチェックリスト(PDF)

自動化していい作業かどうか、VBAかPythonか、最初に避けるべき落とし穴。実務でよく迷うポイントを1枚にまとめました。メールアドレスだけで受け取れます。

無料でチェックリストを受け取る

¥980 ミニキット

コピペで動かせる3スクリプト+自動化チェックリスト

最新ファイルの自動選択・部署名ゆれの正規化・CSV文字コード確認の3本セット。今週の作業を1つだけ楽にするための最小キットです。

ミニキットを見る(¥980)

関連リンクとチェックリスト

関連書籍

Python・pandas関連書籍を、手元で見返せる形にしておきたい場合

pandasのエラー対応は、似た症状を何度も見返すことが多いです。データ前処理や型変換を手元で確認できる本を1冊置いておくと、調べ直しの時間を減らしやすいです。

Python・pandas関連書籍をAmazonで探す

学習サービスとアンケート

このスキルを活かしてさらに前へ進むなら

PythonやExcel自動化スキルを持ったまま、ITエンジニアとして転職したい方には「EBAエデュケーション」が選択肢です。企業が求めるエンジニア像に合わせたカリキュラムで、実務直結のスキルを習得できます。

ITエンジニア転職・EBAエデュケーション →

[アンケート] この記事は役に立ちましたか?


1問だけ回答する