こんにちは、かつコーチです。
pandasを学び始めると必ず出てくるのがDataFrameとSeriesという2つの言葉です。
「同じようなものに見えるけど、何が違うの?」と混乱してしまう方も多いので、この記事で違いと使い分けをしっかり整理します。
DataFrameとSeriesとは?
Seriesの定義:1列分のデータ
Series(シリーズ)とは、ラベル(見出し)付きの1次元のデータのことです。
Excelでいうと「1列分のデータ」に近いイメージです。
import pandas as pd
ages = pd.Series([25, 30, 28], name="年齢")
print(ages)
0 25
1 30
2 28
Name: 年齢, dtype: int64
左側の0, 1, 2はインデックス(各データの位置を示すラベル)と呼ばれるものです。
DataFrameの定義:複数列を持つ表全体
DataFrame(データフレーム)とは、複数のSeriesを列として束ねた、2次元の表形式データのことです。
Excelでいう「シート全体」に近いイメージです。
import pandas as pd
data = {
"名前": ["田中", "佐藤", "鈴木"],
"年齢": [25, 30, 28]
}
df = pd.DataFrame(data)
print(df)
名前 年齢
0 田中 25
1 佐藤 30
2 鈴木 28
つまり、DataFrameから1列だけを取り出すとSeriesになる、という関係にあります。
なぜ2つを区別する必要があるのか
DataFrameとSeriesでは、使えるメソッドや戻り値の形が異なります。
この違いを理解していないと、「あるメソッドがDataFrameでは使えるのにSeriesでは使えない」といったエラーに遭遇したときに原因が分からず戸惑ってしまいます。
例えば、DataFrameの列を1つ取り出すとSeriesになるため、その後の処理も「1列分のデータに対する処理」として書く必要があります。
基本の書き方:DataFrameとSeriesを行き来する
DataFrameから列を取り出すとSeriesになる
import pandas as pd
df = pd.DataFrame({
"名前": ["田中", "佐藤", "鈴木"],
"年齢": [25, 30, 28]
})
age_series = df["年齢"]
print(type(age_series)) # <class 'pandas.core.series.Series'>
DataFrameから複数列を取り出すとDataFrameのまま
一方、列名をリストで指定すると、結果は1列でもDataFrameのままになります。
age_df = df[["年齢"]]
print(type(age_df)) # <class 'pandas.core.frame.DataFrame'>
df["年齢"]とdf[["年齢"]]、見た目はカッコの数が違うだけですが、返ってくる型がまったく異なります。
これは初心者がつまずきやすいポイントの1つです。
型・列名・行数を確認する基本メソッド
DataFrameの中身をざっくり把握するには、以下のメソッドが便利です。
print(df.shape) # (行数, 列数) を表示 -> (3, 2)
print(df.columns) # 列名の一覧
print(df.dtypes) # 各列のデータ型
print(df.info()) # 行数・列名・型・欠損値の有無をまとめて表示
特にdf.info()は、データを読み込んだ直後に必ず実行する習慣をつけておくと、後々のトラブルを防げます。
よくあるつまずきポイント・エラー対処
Series同士の計算で行の対応がずれる
❌Before:インデックスが異なるSeries同士を単純に足し算してしまう
import pandas as pd
s1 = pd.Series([100, 200, 300], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[1, 2, 3])
result = s1 + s2
print(result)
0 NaN
1 210.0
2 320.0
3 NaN
dtype: float64
実際に私がこのコードを初めて実行したとき、「なぜ全部の行が計算されずにNaNが混ざるのか」で数十分悩みました。
原因は、pandasが計算をインデックスをキーにして自動的に対応付ける仕組みになっているためです。
インデックスが一致しない0と3の行は、計算できずにNaN(欠損値)になります。
✅After:計算前にreset_index(drop=True)でインデックスを揃えるか、そもそも同じインデックスを持つデータ同士で計算する
s1_reset = s1.reset_index(drop=True)
s2_reset = s2.reset_index(drop=True)
result = s1_reset + s2_reset
print(result)
「pandasは行番号ではなくインデックスで対応付けている」という前提を知っているかどうかで、原因究明にかかる時間が大きく変わります。
応用・一歩先の使い方
DataFrameの行方向にも同じ考え方が使える
ここまでは列(Series)を中心に説明しましたが、行方向にも同様の考え方があります。df.loc[0]のように行を1行だけ取り出すと、その行はSeriesとして返されます。
行・列どちらの方向でも「1本だけ取り出すとSeries、複数まとめるとDataFrame」というルールは共通です。
メソッドチェーンで処理をつなげる
DataFrameのメソッドは、多くが処理後のDataFrameやSeriesを返すため、.でつなげて書くことができます。
result = df["年齢"].mean()
print(result) # 27.666...
このように処理を連結して書くスタイルは、pandasのコードでは非常によく使われるので、慣れておくと後の記事の理解がスムーズになります。
まとめ
この記事のポイント
- Seriesは1列分のラベル付きデータ、DataFrameは複数列を束ねた表全体
df["列名"]はSeries、df[["列名"]]はDataFrameになる(カッコの数に注意)df.shape・df.columns・df.info()でデータの全体像を把握する習慣をつける- pandasの計算はインデックスをキーに自動対応付けされる点に注意する
次に読むべき記事
DataFrameとSeriesの違いが分かったら、次は実際のデータをCSVファイルから読み込む方法を解説した「read_csvでCSVファイルを読み込む方法とよくあるハマりどころ」に進みましょう。
タグ: Pandas, 初心者向け, 基本操作