🔧 ステップ31: データの加工と変換
データを自在に加工して、分析しやすい形にしよう!
ステップ30では、データの結合を学びました。今回は、DataFrameの列の追加・削除、データの変換、文字列・日付の処理など、データを分析しやすい形に加工する方法を学びます。
📖 このステップで学ぶこと
・列の追加と削除
・apply()での変換
・文字列操作(str)
・日付データの処理
🎯 1. 列の追加と削除
DataFrameに新しい列を追加したり、不要な列を削除したりする方法を学びます。
🔰 新しい列を追加する
新しい列を追加するのは、とても簡単です。
コード:列を追加する
import pandas as pd
# 商品データ
df = pd.DataFrame({
'商品名': ['りんご', 'バナナ', 'みかん'],
'価格': [100, 150, 80],
'数量': [50, 30, 45]
})
print("元のデータ:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ: 商品名 価格 数量 0 りんご 100 50 1 バナナ 150 30 2 みかん 80 45
コード:計算結果で新しい列を追加
# 新しい列を追加(計算結果)
df['在庫金額'] = df['価格'] * df['数量']
print("在庫金額を追加:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
在庫金額を追加: 商品名 価格 数量 在庫金額 0 りんご 100 50 5000 1 バナナ 150 30 4500 2 みかん 80 45 3600
💡 コードの解説
df[‘在庫金額’] = df[‘価格’] * df[‘数量’]
・df[‘在庫金額’]:新しい列名を指定
・= df[‘価格’] * df[‘数量’]:計算結果を代入
・各行の価格と数量を掛け算した結果が入ります
ポイント:
・存在しない列名を指定すると、新しい列が追加されます
・存在する列名を指定すると、上書きされます
コード:固定値で列を追加
# 固定値の列を追加
df['カテゴリ'] = '果物'
print("カテゴリを追加:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
カテゴリを追加: 商品名 価格 数量 在庫金額 カテゴリ 0 りんご 100 50 5000 果物 1 バナナ 150 30 4500 果物 2 みかん 80 45 3600 果物
💡 固定値の追加
df[‘カテゴリ’] = ‘果物’
・全ての行に同じ値「果物」が入ります
・データの分類用にカテゴリ列を追加する場合などに便利です
📝 列を削除する
drop()メソッドで列を削除できます。
コード:列を削除する
# 1つの列を削除
df_dropped = df.drop('カテゴリ', axis=1)
print("カテゴリ列を削除:")
print(df_dropped)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
カテゴリ列を削除: 商品名 価格 数量 在庫金額 0 りんご 100 50 5000 1 バナナ 150 30 4500 2 みかん 80 45 3600
💡 drop()の使い方
df.drop(‘カテゴリ’, axis=1)
・‘カテゴリ’:削除する列名
・axis=1:列を削除することを指定
→ axis=0は行を削除(縦方向)
→ axis=1は列を削除(横方向)
重要:
・drop()は元のDataFrameを変更しません
・削除後の新しいDataFrameを返します
・変更を保持したい場合は、変数に代入します
コード:複数の列を削除
# 複数列を削除
df_multi_drop = df.drop(['在庫金額', 'カテゴリ'], axis=1)
print("複数列を削除:")
print(df_multi_drop)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
複数列を削除: 商品名 価格 数量 0 りんご 100 50 1 バナナ 150 30 2 みかん 80 45
💡 複数列の削除
df.drop([‘在庫金額’, ‘カテゴリ’], axis=1)
・リストで複数の列名を指定できます
・一度に複数の列を削除できます
📘 列名を変更する
rename()メソッドで列名を変更できます。
コード:列名を変更
# 列名を変更
df_renamed = df.rename(columns={
'商品名': 'product_name',
'価格': 'price',
'数量': 'quantity'
})
print("列名を英語に:")
print(df_renamed)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
列名を英語に: product_name price quantity 在庫金額 カテゴリ 0 りんご 100 50 5000 果物 1 バナナ 150 30 4500 果物 2 みかん 80 45 3600 果物
💡 rename()の使い方
df.rename(columns={‘旧名’: ‘新名’})
・columnsに辞書を渡します
・キー:元の列名
・値:新しい列名
・指定しなかった列名はそのままです
📌 列の操作まとめ
| 操作 | 書き方 | 例 |
| 列の追加 | df[‘新列名’] = 値 | df[‘合計’] = df[‘A’] + df[‘B’] |
| 列の削除 | df.drop(‘列名’, axis=1) | df.drop(‘不要列’, axis=1) |
| 列名の変更 | df.rename(columns={}) | df.rename(columns={‘A’: ‘B’}) |
🔄 2. apply()で変換
apply()を使うと、各行や各列に関数を適用できます。複雑な計算や条件分岐に便利です。
🔰 apply()とは?
apply()は、DataFrameの各行(または各列)に対して、同じ処理を繰り返し適用する関数です。
📌 apply()のイメージ
「全ての行に対して、この計算をしてね」と指示するイメージです。
・1行目を処理 → 結果を保存
・2行目を処理 → 結果を保存
・3行目を処理 → 結果を保存
・…以下繰り返し
📝 行に対してapply()を使う
まず、関数を定義して、各行に適用してみましょう。
コード:apply()で合計点を計算
import pandas as pd
# テストデータ
test_df = pd.DataFrame({
'名前': ['太郎', '花子', '次郎'],
'数学': [85, 92, 78],
'英語': [90, 88, 85]
})
print("テストデータ:")
print(test_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
テストデータ: 名前 数学 英語 0 太郎 85 90 1 花子 92 88 2 次郎 78 85
コード:関数を定義してapply()
# 合計点を計算する関数
def calculate_total(row):
return row['数学'] + row['英語']
# apply()で各行に適用(axis=1は行方向)
test_df['合計'] = test_df.apply(calculate_total, axis=1)
print("合計点を追加:")
print(test_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
合計点を追加: 名前 数学 英語 合計 0 太郎 85 90 175 1 花子 92 88 180 2 次郎 78 85 163
💡 コードの解説
def calculate_total(row):
・処理を行う関数を定義します
・引数rowには、1行分のデータが入ります
・row[‘数学’]でその行の数学の点数を取得
test_df.apply(calculate_total, axis=1)
・apply()の第1引数に関数を渡します
・axis=1:行ごとに関数を適用
・全ての行で calculate_total が実行されます
📘 ラムダ式で簡潔に書く
簡単な処理なら、ラムダ式を使うと1行で書けます。
コード:ラムダ式でapply()
# ラムダ式を使う(1行で書ける)
test_df['平均'] = test_df.apply(
lambda row: (row['数学'] + row['英語']) / 2,
axis=1
)
print("平均点を追加:")
print(test_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
平均点を追加: 名前 数学 英語 合計 平均 0 太郎 85 90 175 87.5 1 花子 92 88 180 90.0 2 次郎 78 85 163 81.5
💡 ラムダ式とは?
lambda row: (row[‘数学’] + row[‘英語’]) / 2
・lambda:名前のない関数(無名関数)を作る
・row:引数(1行分のデータ)
・: の後ろ:戻り値(計算結果)
上のラムダ式は、以下と同じ意味です:
def 無名関数(row):
return (row['数学'] + row['英語']) / 2
📘 条件分岐を使った変換
if文を使って、条件に応じた値を設定できます。
コード:評価を追加する
# 評価を決める関数
def get_grade(avg):
if avg >= 90:
return 'A'
elif avg >= 80:
return 'B'
elif avg >= 70:
return 'C'
else:
return 'D'
# 平均点に対してapply()
test_df['評価'] = test_df['平均'].apply(get_grade)
print("評価を追加:")
print(test_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
評価を追加: 名前 数学 英語 合計 平均 評価 0 太郎 85 90 175 87.5 B 1 花子 92 88 180 90.0 A 2 次郎 78 85 163 81.5 B
💡 列に対するapply()
test_df[‘平均’].apply(get_grade)
・test_df[‘平均’]:1つの列(Series)を指定
・.apply(get_grade):その列の各値に関数を適用
・axis指定は不要(列の各値に対して自動的に適用)
DataFrameのapply() vs Seriesのapply():
・DataFrame.apply():行または列単位で適用(axis指定が必要)
・Series.apply():各値に対して適用(axis指定不要)
📌 apply()のポイント
axis=1:行ごとに関数を適用(行データを受け取る)
axis=0:列ごとに関数を適用(列データを受け取る)
Series.apply():各値に関数を適用
ラムダ式:簡単な処理を1行で書ける
📝 3. 文字列操作(str)
文字列データを操作するには、.strアクセサを使います。
🔰 .strとは?
文字列の列に対して、.strを付けると、文字列専用のメソッドが使えます。
コード:サンプルデータの準備
import pandas as pd
# 名前データ
name_df = pd.DataFrame({
'氏名': ['山田太郎', '佐藤花子', '鈴木次郎', '田中美咲'],
'メール': ['yamada@example.com', 'sato@example.com',
'suzuki@example.com', 'tanaka@example.com']
})
print("元のデータ:")
print(name_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ:
氏名 メール
0 山田太郎 yamada@example.com
1 佐藤花子 sato@example.com
2 鈴木次郎 suzuki@example.com
3 田中美咲 tanaka@example.com
📝 大文字・小文字変換
コード:大文字に変換
# 大文字に変換
name_df['メール_大文字'] = name_df['メール'].str.upper()
print("メールを大文字に:")
print(name_df[['メール', 'メール_大文字']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
メールを大文字に:
メール メール_大文字
0 yamada@example.com YAMADA@EXAMPLE.COM
1 sato@example.com SATO@EXAMPLE.COM
2 suzuki@example.com SUZUKI@EXAMPLE.COM
3 tanaka@example.com TANAKA@EXAMPLE.COM
💡 .strの使い方
name_df[‘メール’].str.upper()
・.str:文字列メソッドを使うための「入り口」
・.upper():大文字に変換するメソッド
・全ての行に対して、一度に変換されます
📝 特定の文字を含むか判定
コード:文字列を含むか判定
# 特定の文字を含むか
name_df['山田さん'] = name_df['氏名'].str.contains('山田')
print("山田さんを判定:")
print(name_df[['氏名', '山田さん']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
山田さんを判定:
氏名 山田さん
0 山田太郎 True
1 佐藤花子 False
2 鈴木次郎 False
3 田中美咲 False
💡 contains()の使い方
.str.contains(‘山田’)
・文字列に「山田」が含まれていればTrue
・含まれていなければFalse
・データのフィルタリングに便利です
📘 文字列の分割
コード:文字列を分割
# 姓と名を分割(最初の2文字が姓と仮定)
name_df['姓'] = name_df['氏名'].str[:2] # 最初の2文字
name_df['名'] = name_df['氏名'].str[2:] # 3文字目以降
print("姓名を分割:")
print(name_df[['氏名', '姓', '名']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
姓名を分割:
氏名 姓 名
0 山田太郎 山田 太郎
1 佐藤花子 佐藤 花子
2 鈴木次郎 鈴木 次郎
3 田中美咲 田中 美咲
💡 文字列のスライス
.str[:2]:最初から2文字目まで
.str[2:]:3文字目から最後まで
通常の文字列スライスと同じ書き方です。
コード:@で分割
# メールアドレスを@で分割
name_df['ユーザー名'] = name_df['メール'].str.split('@').str[0]
name_df['ドメイン'] = name_df['メール'].str.split('@').str[1]
print("メールを分割:")
print(name_df[['メール', 'ユーザー名', 'ドメイン']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
メールを分割:
メール ユーザー名 ドメイン
0 yamada@example.com yamada example.com
1 sato@example.com sato example.com
2 suzuki@example.com suzuki example.com
3 tanaka@example.com tanaka example.com
💡 split()の使い方
.str.split(‘@’):@で文字列を分割
・結果はリストになります
・[‘yamada’, ‘example.com’]のような形
.str[0]:リストの1番目を取得
.str[1]:リストの2番目を取得
📘 文字列の置換と削除
コード:文字列の置換
# 商品データ
product_df = pd.DataFrame({
'商品名': ['りんご(赤)', 'バナナ(黄)', 'みかん(橙)'],
'価格': ['¥100', '¥150', '¥80']
})
print("元のデータ:")
print(product_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ:
商品名 価格
0 りんご(赤) ¥100
1 バナナ(黄) ¥150
2 みかん(橙) ¥80
コード:カッコを削除、¥を削除して数値化
# カッコと中身を削除(正規表現を使用)
product_df['商品名_clean'] = product_df['商品名'].str.replace(r'\(.*\)', '', regex=True)
print("カッコを削除:")
print(product_df[['商品名', '商品名_clean']])
# ¥記号を削除して数値に変換
product_df['価格_数値'] = product_df['価格'].str.replace('¥', '').astype(int)
print("\n価格を数値に:")
print(product_df[['価格', '価格_数値']])
print(f"\nデータ型: {product_df['価格_数値'].dtype}")
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
カッコを削除:
商品名 商品名_clean
0 りんご(赤) りんご
1 バナナ(黄) バナナ
2 みかん(橙) みかん
価格を数値に:
価格 価格_数値
0 ¥100 100
1 ¥150 150
2 ¥80 80
データ型: int64
💡 replace()の使い方
.str.replace(‘¥’, ”)
・第1引数:置換したい文字列
・第2引数:置換後の文字列(”で削除)
.str.replace(r’\(.*\)’, ”, regex=True)
・正規表現で「(〜)」を全て削除
・regex=Trueで正規表現モードを有効化
.astype(int)
・文字列を整数に変換
📌 よく使う文字列メソッド
| メソッド | 説明 | 例 |
| .str.upper() | 大文字に変換 | ‘abc’ → ‘ABC’ |
| .str.lower() | 小文字に変換 | ‘ABC’ → ‘abc’ |
| .str.strip() | 前後の空白削除 | ‘ abc ‘ → ‘abc’ |
| .str.replace() | 文字列置換 | ‘¥100’ → ‘100’ |
| .str.split() | 文字列分割 | ‘a@b’ → [‘a’, ‘b’] |
| .str.contains() | 含むか判定 | ‘abc’ に ‘a’ → True |
| .str.len() | 文字数 | ‘abc’ → 3 |
📅 4. 日付データの処理
日付データから年・月・日・曜日などを抽出するには、.dtアクセサを使います。
🔰 日付型への変換
まず、文字列の日付を日付型(datetime)に変換します。
コード:日付型に変換
import pandas as pd
# 売上データ
sales_df = pd.DataFrame({
'日付': ['2024-01-15', '2024-02-20', '2024-03-10', '2024-04-05'],
'売上': [12000, 15000, 13000, 16000]
})
print("元のデータ:")
print(sales_df)
print(f"\n日付の型: {sales_df['日付'].dtype}")
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ:
日付 売上
0 2024-01-15 12000
1 2024-02-20 15000
2 2024-03-10 13000
3 2024-04-05 16000
日付の型: object
💡 現状の問題
日付がobject型(文字列)になっています。
文字列のままでは、年・月・日を取り出せません。
まず、日付型に変換する必要があります。
コード:日付型に変換
# 日付型に変換
sales_df['日付'] = pd.to_datetime(sales_df['日付'])
print("変換後:")
print(sales_df)
print(f"\n日付の型: {sales_df['日付'].dtype}")
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
変換後:
日付 売上
0 2024-01-15 12000
1 2024-02-20 15000
2 2024-03-10 13000
3 2024-04-05 16000
日付の型: datetime64[ns]
💡 to_datetime()の使い方
pd.to_datetime(sales_df[‘日付’])
・文字列を日付型に変換します
・「2024-01-15」のような形式を自動認識
・結果はdatetime64型になります
📝 年・月・日を抽出
日付型に変換したら、.dtで年・月・日などを取り出せます。
コード:年・月・日・曜日を抽出
# 年・月・日・曜日を抽出
sales_df['年'] = sales_df['日付'].dt.year
sales_df['月'] = sales_df['日付'].dt.month
sales_df['日'] = sales_df['日付'].dt.day
sales_df['曜日'] = sales_df['日付'].dt.day_name()
print("日付情報を抽出:")
print(sales_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
日付情報を抽出:
日付 売上 年 月 日 曜日
0 2024-01-15 12000 2024 1 15 Monday
1 2024-02-20 15000 2024 2 20 Tuesday
2 2024-03-10 13000 2024 3 10 Sunday
3 2024-04-05 16000 2024 4 5 Friday
💡 .dtアクセサ
.dtは、日付型の列に対して使える「入り口」です。
・.dt.year:年を取得
・.dt.month:月を取得
・.dt.day:日を取得
・.dt.day_name():曜日名を取得
📘 日付の計算
コード:日付の差を計算
from datetime import datetime
# 今日の日付(例として2024年5月1日を使用)
today = datetime(2024, 5, 1)
# 経過日数を計算
sales_df['経過日数'] = (today - sales_df['日付']).dt.days
print("今日からの経過日数:")
print(sales_df[['日付', '経過日数']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
今日からの経過日数:
日付 経過日数
0 2024-01-15 107
1 2024-02-20 71
2 2024-03-10 52
3 2024-04-05 26
💡 日付の計算
(today – sales_df[‘日付’])
・日付同士の引き算ができます
・結果はTimedelta型(日数の差)
.dt.days
・Timedeltaから日数を取得
📘 四半期・週番号
コード:四半期と週番号
# 四半期
sales_df['四半期'] = sales_df['日付'].dt.quarter
print("四半期:")
print(sales_df[['日付', '月', '四半期']])
# 週番号
sales_df['週番号'] = sales_df['日付'].dt.isocalendar().week
print("\n週番号:")
print(sales_df[['日付', '週番号']])
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
四半期:
日付 月 四半期
0 2024-01-15 1 1
1 2024-02-20 2 1
2 2024-03-10 3 1
3 2024-04-05 4 2
週番号:
日付 週番号
0 2024-01-15 3
1 2024-02-20 8
2 2024-03-10 10
3 2024-04-05 14
📌 よく使う日付メソッド
| プロパティ | 説明 |
| .dt.year | 年(2024など) |
| .dt.month | 月(1〜12) |
| .dt.day | 日(1〜31) |
| .dt.dayofweek | 曜日(0=月曜〜6=日曜) |
| .dt.quarter | 四半期(1〜4) |
| .dt.is_month_start | 月初かどうか(True/False) |
| .dt.is_month_end | 月末かどうか(True/False) |
🎨 5. 実践的なデータ加工
📘 例1:顧客セグメント作成
コード:年齢層と購入ランクでセグメント化
import pandas as pd
# 顧客データ
customer_df = pd.DataFrame({
'顧客ID': [1, 2, 3, 4, 5, 6],
'年齢': [25, 35, 45, 28, 52, 38],
'購入金額': [50000, 120000, 30000, 80000, 150000, 45000]
})
print("元のデータ:")
print(customer_df)
# 年齢層を作成する関数
def age_group(age):
if age < 30:
return '20代'
elif age < 40:
return '30代'
elif age < 50:
return '40代'
else:
return '50代以上'
# 購入ランクを作成する関数
def purchase_rank(amount):
if amount >= 100000:
return 'プラチナ'
elif amount >= 70000:
return 'ゴールド'
elif amount >= 40000:
return 'シルバー'
else:
return 'ブロンズ'
# apply()で適用
customer_df['年齢層'] = customer_df['年齢'].apply(age_group)
customer_df['ランク'] = customer_df['購入金額'].apply(purchase_rank)
print("\nセグメント追加:")
print(customer_df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ: 顧客ID 年齢 購入金額 0 1 25 50000 1 2 35 120000 2 3 45 30000 3 4 28 80000 4 5 52 150000 5 6 38 45000 セグメント追加: 顧客ID 年齢 購入金額 年齢層 ランク 0 1 25 50000 20代 シルバー 1 2 35 120000 30代 プラチナ 2 3 45 30000 40代 ブロンズ 3 4 28 80000 20代 ゴールド 4 5 52 150000 50代以上 プラチナ 5 6 38 45000 30代 シルバー
📘 例2:データクリーニング
コード:汚れたデータをクリーニング
# 汚れたデータ
dirty_df = pd.DataFrame({
'商品名': [' りんご ', 'バナナ', 'みかん ', ' ぶどう'],
'価格': ['100円', '¥150', '80', '300円'],
'在庫': ['50個', '30', '45個', '20']
})
print("元のデータ(汚れている):")
print(dirty_df)
# クリーニング
clean_df = dirty_df.copy()
# 1. 前後の空白を削除
clean_df['商品名'] = clean_df['商品名'].str.strip()
# 2. 価格から不要な文字を削除して数値化
clean_df['価格'] = (
clean_df['価格']
.str.replace('円', '')
.str.replace('¥', '')
.astype(int)
)
# 3. 在庫から「個」を削除して数値化
clean_df['在庫'] = (
clean_df['在庫']
.str.replace('個', '')
.astype(int)
)
print("\nクリーニング後:")
print(clean_df)
print("\nデータ型:")
print(clean_df.dtypes)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ(汚れている):
商品名 価格 在庫
0 りんご 100円 50個
1 バナナ ¥150 30
2 みかん 80 45個
3 ぶどう 300円 20
クリーニング後:
商品名 価格 在庫
0 りんご 100 50
1 バナナ 150 30
2 みかん 80 45
3 ぶどう 300 20
データ型:
商品名 object
価格 int64
在庫 int64
dtype: object
💡 クリーニングのポイント
1. .str.strip():前後の空白を削除
2. .str.replace():不要な文字を削除
3. .astype(int):数値型に変換
この流れで、汚れたデータを分析可能な形に整えます。
📝 練習問題
ここまで学んだことを、実際に手を動かして確認しましょう。
問題1:列の追加(初級)
📋 問題
以下のデータに「合計点」列を追加してください。
df = pd.DataFrame({
'名前': ['太郎', '花子', '次郎'],
'国語': [80, 90, 75],
'数学': [85, 92, 78]
})
※ 画面が小さい場合は、コードブロックを横にスクロールできます
解答例を見る
コード
import pandas as pd
df = pd.DataFrame({
'名前': ['太郎', '花子', '次郎'],
'国語': [80, 90, 75],
'数学': [85, 92, 78]
})
print("元のデータ:")
print(df)
# 合計点を追加
df['合計点'] = df['国語'] + df['数学']
print("\n合計点を追加:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ: 名前 国語 数学 0 太郎 80 85 1 花子 90 92 2 次郎 75 78 合計点を追加: 名前 国語 数学 合計点 0 太郎 80 85 165 1 花子 90 92 182 2 次郎 75 78 153
問題2:文字列の大文字変換(初級)
📋 問題
以下のメールアドレスをすべて大文字に変換してください。
df = pd.DataFrame({
'メール': ['taro@example.com', 'hanako@example.com', 'jiro@example.com']
})
※ 画面が小さい場合は、コードブロックを横にスクロールできます
解答例を見る
コード
import pandas as pd
df = pd.DataFrame({
'メール': ['taro@example.com', 'hanako@example.com', 'jiro@example.com']
})
print("元のデータ:")
print(df)
# 大文字に変換
df['メール_大文字'] = df['メール'].str.upper()
print("\n大文字に変換:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ:
メール
0 taro@example.com
1 hanako@example.com
2 jiro@example.com
大文字に変換:
メール メール_大文字
0 taro@example.com TARO@EXAMPLE.COM
1 hanako@example.com HANAKO@EXAMPLE.COM
2 jiro@example.com JIRO@EXAMPLE.COM
問題3:apply()で評価追加(中級)
📋 問題
以下のデータに、点数に応じた評価を追加してください。
90点以上: A、80点以上: B、70点以上: C、それ以下: D
df = pd.DataFrame({
'名前': ['太郎', '花子', '次郎', '美咲'],
'点数': [95, 82, 68, 88]
})
※ 画面が小さい場合は、コードブロックを横にスクロールできます
解答例を見る
コード
import pandas as pd
df = pd.DataFrame({
'名前': ['太郎', '花子', '次郎', '美咲'],
'点数': [95, 82, 68, 88]
})
print("元のデータ:")
print(df)
# 評価関数
def get_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
else:
return 'D'
# apply()で評価を追加
df['評価'] = df['点数'].apply(get_grade)
print("\n評価を追加:")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ: 名前 点数 0 太郎 95 1 花子 82 2 次郎 68 3 美咲 88 評価を追加: 名前 点数 評価 0 太郎 95 A 1 花子 82 B 2 次郎 68 D 3 美咲 88 B
問題4:日付から月を抽出(中級)
📋 問題
以下の日付データから「月」を抽出し、月ごとの売上合計を計算してください。
df = pd.DataFrame({
'日付': ['2024-01-15', '2024-01-20', '2024-02-10', '2024-02-25'],
'売上': [10000, 12000, 15000, 13000]
})
※ 画面が小さい場合は、コードブロックを横にスクロールできます
解答例を見る
コード
import pandas as pd
df = pd.DataFrame({
'日付': ['2024-01-15', '2024-01-20', '2024-02-10', '2024-02-25'],
'売上': [10000, 12000, 15000, 13000]
})
print("元のデータ:")
print(df)
# 日付型に変換
df['日付'] = pd.to_datetime(df['日付'])
# 月を抽出
df['月'] = df['日付'].dt.month
print("\n月を抽出:")
print(df)
# 月ごとの売上合計
monthly_sales = df.groupby('月')['売上'].sum()
print("\n月ごとの売上合計:")
print(monthly_sales)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ:
日付 売上
0 2024-01-15 10000
1 2024-01-20 12000
2 2024-02-10 15000
3 2024-02-25 13000
月を抽出:
日付 売上 月
0 2024-01-15 10000 1
1 2024-01-20 12000 1
2 2024-02-10 15000 2
3 2024-02-25 13000 2
月ごとの売上合計:
月
1 22000
2 28000
Name: 売上, dtype: int64
問題5:総合演習(上級)
📋 問題
以下の汚れたデータを:
1. 空白を削除
2. 価格を数値化
3. カテゴリコードを追加(果物: FR、野菜: VG)
4. 商品コードを生成(カテゴリコード + 3桁の番号)
5. カテゴリごとの合計金額を計算
df = pd.DataFrame({
'商品名': [' りんご', 'にんじん ', ' バナナ ', 'トマト'],
'カテゴリ': ['果物', '野菜', '果物', '野菜'],
'価格': ['100円', '80円', '150円', '120円'],
'番号': [1, 1, 2, 2]
})
※ 画面が小さい場合は、コードブロックを横にスクロールできます
解答例を見る
コード
import pandas as pd
df = pd.DataFrame({
'商品名': [' りんご', 'にんじん ', ' バナナ ', 'トマト'],
'カテゴリ': ['果物', '野菜', '果物', '野菜'],
'価格': ['100円', '80円', '150円', '120円'],
'番号': [1, 1, 2, 2]
})
print("元のデータ(汚れている):")
print(df)
# 1. 空白を削除
df['商品名'] = df['商品名'].str.strip()
print("\n1. 空白削除:")
print(df)
# 2. 価格を数値化
df['価格_数値'] = df['価格'].str.replace('円', '').astype(int)
print("\n2. 価格を数値化:")
print(df[['商品名', '価格', '価格_数値']])
# 3. カテゴリコード
category_map = {'果物': 'FR', '野菜': 'VG'}
df['カテゴリコード'] = df['カテゴリ'].map(category_map)
print("\n3. カテゴリコード:")
print(df[['商品名', 'カテゴリ', 'カテゴリコード']])
# 4. 商品コード生成
df['商品コード'] = (
df['カテゴリコード'] +
df['番号'].astype(str).str.zfill(3)
)
print("\n4. 商品コード:")
print(df[['商品名', '商品コード']])
# 5. カテゴリごとの合計
category_total = df.groupby('カテゴリ')['価格_数値'].sum()
print("\n5. カテゴリごとの合計金額:")
print(category_total)
print("\n【最終データ】")
print(df)
※ 画面が小さい場合は、コードブロックを横にスクロールできます
実行結果
元のデータ(汚れている):
商品名 カテゴリ 価格 番号
0 りんご 果物 100円 1
1 にんじん 野菜 80円 1
2 バナナ 果物 150円 2
3 トマト 野菜 120円 2
1. 空白削除:
商品名 カテゴリ 価格 番号
0 りんご 果物 100円 1
1 にんじん 野菜 80円 1
2 バナナ 果物 150円 2
3 トマト 野菜 120円 2
2. 価格を数値化:
商品名 価格 価格_数値
0 りんご 100円 100
1 にんじん 80円 80
2 バナナ 150円 150
3 トマト 120円 120
3. カテゴリコード:
商品名 カテゴリ カテゴリコード
0 りんご 果物 FR
1 にんじん 野菜 VG
2 バナナ 果物 FR
3 トマト 野菜 VG
4. 商品コード:
商品名 商品コード
0 りんご FR001
1 にんじん VG001
2 バナナ FR002
3 トマト VG002
5. カテゴリごとの合計金額:
カテゴリ
果物 250
野菜 200
Name: 価格_数値, dtype: int64
【最終データ】
商品名 カテゴリ 価格 番号 価格_数値 カテゴリコード 商品コード
0 りんご 果物 100円 1 100 FR FR001
1 にんじん 野菜 80円 1 80 VG VG001
2 バナナ 果物 150円 2 150 FR FR002
3 トマト 野菜 120円 2 120 VG VG002
🎯 このステップのまとめ
✅ 学んだこと
✓ 列の追加・削除・名前変更ができる
✓ apply()で関数を適用できる
✓ .strで文字列操作ができる
✓ .dtで日付操作ができる
✓ データクリーニングの実践的な手法
💡 次のステップに進む前に確認
以下のことができるようになったか確認しましょう:
□ 列の追加と削除ができる
□ apply()で関数を適用できる
□ 文字列メソッドを使える
□ 日付から情報を抽出できる
□ データクリーニングができる
これらができたら、次のステップに進みましょう!
❓ よくある質問
Q1: apply()は遅いと聞きましたが?
A: はい、ベクトル演算の方が速いです。
df['A'] + df['B']のような単純な計算は、apply()を使わず直接計算しましょう。
複雑な条件分岐がある場合にapply()を使います。
Q2: ラムダ式と通常の関数、どちらを使うべき?
A: 簡単な処理:ラムダ式(1行で書ける)
複雑な処理:通常の関数を定義(読みやすい)
Q3: 文字列メソッドが効かない場合は?
A: 列のデータ型がobject(文字列)型か確認してください。
数値型だと.strは使えません。df['列名'].dtypeで確認できます。
Q4: 日付型への変換に失敗します
A: 日付のフォーマットが統一されていない可能性があります。
pd.to_datetime(df['日付'], errors='coerce')で、変換できない値をNaNにできます。
Q5: 複数の列を一度に削除したいです
A: df.drop(['列1', '列2', '列3'], axis=1)のようにリストで指定できます。
またはdf[['残したい列1', '残したい列2']]で残したい列だけ選択する方法もあります。
学習メモ
Pythonデータ分析入門 - Step 31