Pythonでデータ分析を行う際、最も頻繁に利用するライブラリの一つがPandasです。
その中心的なデータ構造であるDataFrame(データフレーム)をどのように作成するかは、効率的なデータ処理の第一歩となります。
特に、Pythonの標準機能である「リスト」からDataFrameを生成する手法は、外部データの読み込みや計算結果の集計において非常に汎用性が高いスキルです。
本記事では、1次元リストから多次元リスト、さらには辞書形式との組み合わせまで、実務で役立つ具体的な手法と使い分けについて詳しく解説します。
Pandas DataFrame作成の基本
PandasのDataFrameは、行と列を持つ2次元の表形式データ構造です。
リストからDataFrameを作成する際には、主にpd.DataFrame()というコンストラクタを使用します。
このコンストラクタは柔軟性が高く、引数に渡すリストの構造(次元数や要素の種類)によって、生成される表の形が変化します。
まずは、最もシンプルな1次元リストの変換から見ていきましょう。
1次元リストからDataFrameを作成する
1次元リスト(単一の要素が並ぶリスト)をDataFrameに変換すると、1列のみを持つDataFrameが作成されます。
これは、時系列データや特定の計測値の羅列を扱う際に便利です。
基本的な作成方法
以下のコードは、数値が格納されたシンプルなリストをDataFrameに変換する例です。
import pandas as pd
# 1次元リストの定義
data_list = [100, 200, 300, 400, 500]
# DataFrameの作成
df = pd.DataFrame(data_list)
# 結果の表示
print(df)
0
0 100
1 200
2 300
3 400
4 500
デフォルトの状態では、列名(カラム名)は0となり、行インデックスも0からの連番が自動的に割り当てられます。
列名とインデックスを指定する
実務では、列名が数値のままだとデータの意味が分かりにくいため、columns引数を使用して明示的に名前を指定するのが一般的です。
import pandas as pd
data_list = [100, 200, 300, 400, 500]
# 列名(columns)と行ラベル(index)を指定
df = pd.DataFrame(data_list, columns=['Price'], index=['A', 'B', 'C', 'D', 'E'])
print(df)
Price
A 100
B 200
C 300
D 400
E 500
このように、columns=['列名']と記述することで、データの意味を明確にした表を構成できます。
2次元リスト(ネストされたリスト)から作成する
複数の行と列を持つデータを扱う場合、リストの中にリストが含まれる「2次元リスト(ネストされたリスト)」を使用します。
この場合、外側のリストの各要素(内側のリスト)が1つの「行」として扱われます。
行データとしてのリスト構造
以下の例では、名前、年齢、都市名という3つの属性を持つデータを3名分定義しています。
import pandas as pd
# 2次元リスト(各要素が行データに対応)
data_nested = [
['Alice', 25, 'Tokyo'],
['Bob', 30, 'Osaka'],
['Charlie', 35, 'Nagoya']
]
# カラム名を指定して作成
df = pd.DataFrame(data_nested, columns=['Name', 'Age', 'City'])
print(df)
Name Age City
0 Alice 25 Tokyo
1 Bob 30 Osaka
2 Charlie 35 Nagoya
この方法の利点は、データの行方向のまとまりが直感的に理解しやすい点にあります。
データベースのレコードのような形式でデータを保持している場合に非常に有効です。
要素数が不揃いな場合の挙動
もし内側のリストの長さが揃っていない場合、Pandasは欠損している部分をNaN(Not a Number)として処理します。
import pandas as pd
# 3つ目の要素が欠けているリスト
data_incomplete = [
['Alice', 25, 'Tokyo'],
['Bob', 30], # 都市名が不足
['Charlie', 35, 'Nagoya']
]
df = pd.DataFrame(data_incomplete, columns=['Name', 'Age', 'City'])
print(df)
Name Age City
0 Alice 25 Tokyo
1 Bob 30 None
2 Charlie 35 Nagoya
Pythonの標準リストにNoneが含まれている場合や要素が足りない場合、Pandasはそれを適切に処理しますが、計算エラーを防ぐために作成後のデータクレンジングが必要になることを覚えておきましょう。
辞書形式のリスト(List of Dictionaries)から作成する
Web APIのレスポンス(JSON形式)などで非常によく見られるのが、「辞書を要素に持つリスト」です。
この形式からDataFrameを作成すると、辞書のキー(Key)が自動的に列名として採用されます。
JSONライクなデータ構造の変換
import pandas as pd
# 辞書のリスト
data_dicts = [
{'Name': 'Alice', 'Age': 25, 'City': 'Tokyo'},
{'Name': 'Bob', 'Age': 30, 'City': 'Osaka'},
{'Name': 'Charlie', 'Age': 35, 'City': 'Nagoya'}
]
# 辞書自体に列情報が含まれるため、columns指定なしで作成可能
df = pd.DataFrame(data_dicts)
print(df)
Name Age City
0 Alice 25 Tokyo
1 Bob 30 Osaka
2 Charlie 35 Nagoya
この手法の最大のメリットは、列の順番や欠損をPandasが自動的に調整してくれる点です。
例えば、辞書のキーの順番が各要素でバラバラであっても、同じキー同士が正しく1つの列に集約されます。
特定の列のみを抽出して作成する
辞書に多くのデータが含まれているものの、その一部だけをDataFrameにしたい場合は、columns引数で必要なキーのみを指定します。
# 'Name'と'City'のみを抽出
df_subset = pd.DataFrame(data_dicts, columns=['Name', 'City'])
print(df_subset)
Name City
0 Alice Tokyo
1 Bob Osaka
2 Charlie Nagoya
指定した列名が辞書のキーに存在しない場合、その列はNaNで埋められた状態で作成されます。
複数のリストを「列」として結合して作成する
これまでは「行」を意識した作成方法でしたが、「名前リスト」「年齢リスト」のように、項目ごとの独立したリストを組み合わせて表を作ることもあります。
zip関数を利用する方法
Pythonの標準関数であるzip()を使用すると、複数のリストを並列にまとめ、2次元構造に変換できます。
import pandas as pd
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
# zipでまとめてリスト化し、DataFrameへ
df = pd.DataFrame(list(zip(names, ages)), columns=['Name', 'Age'])
print(df)
辞書を経由する方法(推奨)
よりコードの可読性を高めるには、リストを値に持つ辞書を作成し、それをDataFrameに渡す方法が推奨されます。
import pandas as pd
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
# リストを値に持つ辞書を定義
data_map = {
'Name': names,
'Age': ages
}
df = pd.DataFrame(data_map)
print(df)
この方法では、「列名:データのリスト」という対応関係がコード上で一目でわかるため、メンテナンス性が向上します。
DataFrame作成時のデータ型(dtype)の制御
PandasはリストからDataFrameを作成する際、要素の内容から自動的にデータ型(dtype)を推論します。
しかし、メモリ節約や後続の処理の都合上、型を明示したい場合があります。
dtype引数の活用
特に浮動小数点数(float)として扱いたい場合や、特定のビット数を指定したい場合に有効です。
import pandas as pd
data = [1, 2, 3]
# 明示的にfloat型を指定
df = pd.DataFrame(data, columns=['Numbers'], dtype='float64')
print(df)
print(df.dtypes)
Numbers
0 1.0
1 2.0
2 3.0
Numbers float64
dtype: object
もし、リスト内に整数と文字列が混在している場合、Pandasは最も汎用的な型であるobject型を選択します。
これは計算速度を低下させる原因になるため、可能な限り同じ型のデータでリストを構成するか、作成時に適切な型変換を行うことが重要です。
大規模データにおけるリストからの作成とパフォーマンス
数万行、数百万行といった大規模なデータをリストからDataFrameに変換する場合、パフォーマンスが問題になることがあります。
| データ構造 | 作成速度 | 特徴 |
|---|---|---|
| Pythonリストのリスト | 中速 | 標準的だがメモリ消費はやや多い |
| 辞書のリスト | 低速 | 柔軟性は高いがオーバーヘッドが大きい |
| NumPy配列(ndarray) | 高速 | 数値計算に最適でメモリ効率が良い |
大規模な数値を扱う場合は、一度numpy.arrayを経由してからDataFrame化することで、処理速度とメモリ効率を大幅に改善できる可能性があります。
import pandas as pd
import numpy as np
# 大規模なデータを想定したNumPy配列
data_np = np.random.rand(100000, 3)
# 配列からDataFrameを作成
df = pd.DataFrame(data_np, columns=['val1', 'val2', 'val3'])
数値データのみのリストであれば、Pandasに渡す直前にnp.array(my_list)とするだけでも効果があります。
よくあるエラーと解決策
リストからDataFrameを作成する際、初心者が陥りやすいミスとその対処法をまとめます。
1. 形状の不一致(Shape Mismatch)
2次元リストの各行の要素数と、columnsで指定したリストの長さが一致しない場合に発生します。
- 症状:
ValueError: Shape of passed values is..., indices imply... - 解決策:データの各要素の数と、列名のリストの要素数が同じであることを確認してください。
2. 1次元リストを列として追加したいのに「行」になる
辞書形式を使わずに単一のリストをpd.DataFrame([list])のように渡すと、1行多列のデータになってしまいます。
- 解決策:縦の列にしたい場合は、リストをそのまま渡すか、
.T(転置操作)を使用して行列を入れ替えます。
まとめ
PandasのDataFrameをリストから作成する方法は、データの持ち方によっていくつかのパターンに分かれます。
- 1次元リスト:単一列のデータを作成する場合に使用。
- 2次元リスト:行ベースのデータ構造(レコード形式)を変換する場合に最適。
- 辞書のリスト:JSON形式などの外部データ連携において、列名を自動付与したい場合に便利。
- 辞書(値がリスト):列ごとのデータを結合して表を作る際に最も可読性が高い。
それぞれの特徴を理解し、元となるデータの形式に合わせて最適な手法を選択することで、分析の前処理をよりスムーズに進めることができます。
特に実務では、データ型の指定(dtype)や欠損値への配慮もセットで行う習慣をつけましょう。
これからPandasを本格的に活用していく方は、まずは手元のリストデータをDataFrameに変換し、df.head()などで構造を確認するところから始めてみてください。
