pandas の基礎知識¶

本資料では、時間割編成問題に限らず、あらゆる表形式データの処理に役立つ pandas の基本操作を段階的に学ぶ。各節には解説と練習問題が含まれ、最後には補足として機能別操作一覧も掲載している。


1. データ構造の理解¶

実行例¶

In [1]:
import pandas as pd

data = {'名前': ['田中', '佐藤', '鈴木'], '年齢': [25, 30, 22]}
df = pd.DataFrame(data)
print(type(df))           # DataFrame 型
print(type(df['名前']))   # Series 型
<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.series.Series'>

解説¶

pandas の表形式データは DataFrame 型として扱われる。各列は Series として個別に取り出すことができ、列単位での演算や処理が可能である。これら2つのデータ構造の違いを理解することで、pandas 操作の意図や制限を正しく把握できる。

練習問題¶

  1. df['年齢'] のデータ型は何か。また、それに対してどのような操作が可能か。
  2. df[['名前']] で取得されるオブジェクトの型は何か。df['名前'] と比較して違いを述べること。

2. データの読み書き¶

実行例¶

In [2]:
df.to_csv('example.csv', index=False)
df2 = pd.read_csv('example.csv', encoding='utf-8')
print(df2)
   名前  年齢
0  田中  25
1  佐藤  30
2  鈴木  22

解説¶

pandas では CSV ファイル形式を通じてデータの読み書きが可能である。read_csv() は外部ファイルから DataFrame を構築する関数で、to_csv() は DataFrame を保存するために使用する。文字コードやインデックスの扱いには注意が必要である。

練習問題¶

  1. read_csv() 関数に encoding='utf-8' を指定する目的を簡潔に述べること。
  2. to_csv() で index=False を指定しなかった場合、CSVファイルにはどのような内容が含まれるか。

3. データの確認¶

実行例¶

In [3]:
print(df.head(2))
print(df.columns)
   名前  年齢
0  田中  25
1  佐藤  30
Index(['名前', '年齢'], dtype='object')

解説¶

head() は読み込んだデータの先頭行を確認するために使う。columns 属性は列名の一覧を確認する手段である。これらはデータの中身を理解し、次に行う処理方針を立てるうえでの出発点になる。

練習問題¶

  1. 最初の10行を確認するにはどのようなコードを書けばよいか。
  2. 読み込んだデータにどのような列があるか確認したいとき、どのプロパティを参照するか。

4. 列と行の選択¶

実行例¶

In [4]:
print(df['名前'])
print(df[['名前', '年齢']])
0    田中
1    佐藤
2    鈴木
Name: 名前, dtype: object
   名前  年齢
0  田中  25
1  佐藤  30
2  鈴木  22

解説¶

1列だけ取り出す場合は df['列名'] を使う。複数列を取り出すには、リスト ['列1', '列2'] を使って df[リスト] という形式で記述する。型が異なること(Series と DataFrame)に注意すること。

練習問題¶

  1. 「年齢」列を DataFrame 型として取り出すにはどう書くか。
  2. 「名前」列と「年齢」列の両方を同時に抽出するコードを書くこと。

5. 条件によるフィルタリング¶

実行例¶

In [5]:
df[df['年齢'] > 25]
Out[5]:
名前 年齢
1 佐藤 30

解説¶

条件に合致する行を取り出すには、df[条件式] を使う。条件式 は df['列名'] 演算子 値 の形で記述し、真となる行だけが抽出される。比較演算子には ==, !=, <, >, <=, >= がある。

練習問題¶

  1. 「年齢」が30以上の人のみを抽出するには、どのようなコードを書くか。
  2. 「名前」が「佐藤」の行だけを抽出するには、どのような条件式を使うか。

6. 列の加工と追加¶

実行例¶

In [6]:
df['年齢カテゴリ'] = ['若手', 'ベテラン', '若手']
df
Out[6]:
名前 年齢 年齢カテゴリ
0 田中 25 若手
1 佐藤 30 ベテラン
2 鈴木 22 若手

解説¶

DataFrame に新しい列を追加するには、df['新しい列名'] = 値 の形で代入する。元の列に基づいて値を計算して追加することもできる。ここでは固定値のリストを代入しているが、後の節で関数的に生成する方法(apply())も学ぶ。

練習問題¶

  1. すべての人を「不明」というカテゴリで分類する列「属性」を追加すること。
  2. 「年齢」列が存在する前提で、新たな列「2倍年齢」に年齢×2 の値を追加すること。

7. 集計とグループ処理¶

実行例¶

In [7]:
df['部署'] = ['A', 'B', 'A']

print(df)
print(df['名前'].value_counts())
print(df.groupby('部署')['年齢'].mean())
   名前  年齢 年齢カテゴリ 部署
0  田中  25     若手  A
1  佐藤  30   ベテラン  B
2  鈴木  22     若手  A
名前
田中    1
佐藤    1
鈴木    1
Name: count, dtype: int64
部署
A    23.5
B    30.0
Name: 年齢, dtype: float64

解説¶

value_counts() は、ある列に登場する値の個数をカウントするメソッドである。これは Series に対して使い、分布を把握できる。groupby() はカテゴリ列を指定してグループ化し、そのグループごとに平均(.mean())や合計(.sum())を算出できる。

練習問題¶

  1. 「名前」列に登場する名前ごとの出現回数を集計したいとき、どの関数をどのように使えばよいか。その戻り値の型も併せて説明すること。
  2. 「部署」列ごとに年齢の最大値を求めたいとき、どのようなコードを書けばよいか。

8. 欠損値の処理¶

実行例¶

In [8]:
data = {'名前': ['田中', '佐藤', '鈴木'], '年齢': [25, None, 22]}
df = pd.DataFrame(data)

print(df.isnull())
print(df['年齢'].fillna(0))
      名前     年齢
0  False  False
1  False   True
2  False  False
0    25.0
1     0.0
2    22.0
Name: 年齢, dtype: float64

解説¶

欠損値(NaN)は現実のデータで頻出し、事前に検出と処理が必要である。isnull() は欠損の有無を確認するため、fillna() は欠損を任意の値で埋めるために使用する。

練習問題¶

  1. 「年齢」列の欠損値があるかどうかを確認するにはどのようなコードを書くか。結果は何型で返されるか。
  2. 「年齢」列の欠損値をすべて「-1」で埋めるにはどう書くか。fillna() を使って記述すること。

9. ソートと重複処理¶

実行例¶

In [9]:
data = {'名前': ['田中', '佐藤', '田中'], '年齢': [25, 30, 25]}
df = pd.DataFrame(data)

print(df)
print(df.sort_values(by='年齢', ascending=False))
print(df.drop_duplicates())
   名前  年齢
0  田中  25
1  佐藤  30
2  田中  25
   名前  年齢
1  佐藤  30
0  田中  25
2  田中  25
   名前  年齢
0  田中  25
1  佐藤  30

解説¶

ソートは sort_values() によって任意の列で行順を変更できる。また、重複を削除するには drop_duplicates() を使う。特定の列に限定して重複判定することも可能である。

練習問題¶

  1. 「名前」列を昇順、「年齢」列を降順で並べ替えるにはどのように sort_values() を記述すればよいか。
  2. 同じ「名前」と「年齢」のペアが複数ある場合、それらの重複を除きたいときはどうするか。drop_duplicates() を使って記述すること。

10. 関数適用による列の生成(apply)¶

実行例¶

In [10]:
def age_category(age):
    return '若手' if age < 30 else 'ベテラン'

print(df)

df['区分'] = df['年齢'].apply(age_category)
print(df)
   名前  年齢
0  田中  25
1  佐藤  30
2  田中  25
   名前  年齢    区分
0  田中  25    若手
1  佐藤  30  ベテラン
2  田中  25    若手

解説¶

apply() は Series の各要素に対して関数を適用できるメソッドで、複雑な条件に基づく分類や変換を行う際に有効である。関数は def で定義したものでも lambda でも可能である。

練習問題¶

  1. 年齢が30歳以上であれば「成人」、それ未満であれば「未成年」とする列「年齢区分」を追加すること。
  2. 「名前」列に対し、名前が2文字であれば「短」、3文字以上であれば「長」とする列を追加すること。