Step 31:データの加工と変換

🔧 ステップ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

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE