STEP 9:データ変換の基本パターン

🔧 STEP 9: データ変換の基本パターン

カラム操作・文字列処理・日付処理・カテゴリ変換をマスターしよう

📋 このステップで学ぶこと

  • カラムの追加・削除・変更・並び替え
  • 条件に基づくデータ変更(loc、np.where、np.select)
  • 文字列操作(split、strip、replace、contains、extract)
  • 日付データの処理(変換、抽出、計算、フィルタ)
  • カテゴリデータの変換(ラベルエンコーディング、ワンホットエンコーディング)

⏱️ 学習時間の目安:2.5時間

📝 練習問題:15問(基礎6問・応用6問・発展3問)

🎯 1. カラムの追加・削除・変更

1-1. データ変換とは?

ETLの「T(Transform)」の中心的な作業がデータ変換です。
生のデータを分析・機械学習に使える形に整えます。

🍳 例え話:料理の下ごしらえ

野菜をそのまま鍋に入れることはありません。
皮を剥く(不要なカラムを削除)、切る(文字列を分割)、下味をつける(データ型を変換)…
データ変換は、分析という「料理」のための下ごしらえです!

1-2. 新しいカラムを追加する

# ===== カラムの追加方法 ===== import pandas as pd df = pd.DataFrame({ ‘product’: [‘ノートPC’, ‘マウス’, ‘キーボード’], ‘price’: [89800, 1980, 4500], ‘quantity’: [2, 5, 3] }) print(“=== 元のデータ ===”) print(df) # 方法1: 直接代入(最も一般的) df[‘total’] = df[‘price’] * df[‘quantity’] # 方法2: 税込価格を追加 df[‘total_with_tax’] = df[‘total’] * 1.1 # 方法3: assign()を使う(元のDataFrameは変更されない) df2 = df.assign( discount=lambda x: x[‘total’] * 0.1, final_price=lambda x: x[‘total’] – x[‘total’] * 0.1 ) print(“\n=== カラム追加後 ===”) print(df) print(“\n=== assign()で追加 ===”) print(df2)
【実行結果】 === 元のデータ === product price quantity 0 ノートPC 89800 2 1 マウス 1980 5 2 キーボード 4500 3 === カラム追加後 === product price quantity total total_with_tax 0 ノートPC 89800 2 179600 197560.0 1 マウス 1980 5 9900 10890.0 2 キーボード 4500 3 13500 14850.0

1-3. カラムを削除する

# ===== カラムの削除方法 ===== import pandas as pd df = pd.DataFrame({ ‘A’: [1, 2, 3], ‘B’: [4, 5, 6], ‘C’: [7, 8, 9], ‘D’: [10, 11, 12] }) print(“=== 元のデータ ===”) print(df) # 方法1: drop()で削除(元のDataFrameは変更されない) df1 = df.drop(‘C’, axis=1) print(“\n=== drop(‘C’)後 ===”) print(df1) # 方法2: 複数カラムを削除 df2 = df.drop([‘B’, ‘C’], axis=1) print(“\n=== drop([‘B’, ‘C’])後 ===”) print(df2) # 方法3: inplace=Trueで元のDataFrameを変更 df_copy = df.copy() df_copy.drop(‘D’, axis=1, inplace=True) print(“\n=== inplace=True後 ===”) print(df_copy) # 方法4: del文で削除(元のDataFrameを変更) df_copy2 = df.copy() del df_copy2[‘A’] print(“\n=== del後 ===”) print(df_copy2)
⚠️ drop()の注意点
  • drop()だけでは元のDataFrameは変更されない
  • 変更を反映するにはdf = df.drop(...)inplace=Trueを使う
  • axis=1は「列方向」、axis=0は「行方向」

1-4. カラム名を変更する

# ===== カラム名の変更方法 ===== import pandas as pd df = pd.DataFrame({ ‘old_name1’: [1, 2, 3], ‘old_name2’: [4, 5, 6] }) print(“=== 元のデータ ===”) print(df) # 方法1: rename()で特定のカラムを変更 df1 = df.rename(columns={ ‘old_name1’: ‘new_name1’, ‘old_name2’: ‘new_name2’ }) print(“\n=== rename()後 ===”) print(df1) # 方法2: すべてのカラム名を一度に変更 df2 = df.copy() df2.columns = [‘A’, ‘B’] print(“\n=== columns属性で変更後 ===”) print(df2) # 方法3: 日本語カラム名を英語に一括変換 df_jp = pd.DataFrame({ ‘商品名’: [‘ノートPC’, ‘マウス’], ‘価格’: [89800, 1980], ‘数量’: [2, 5] }) column_mapping = { ‘商品名’: ‘product’, ‘価格’: ‘price’, ‘数量’: ‘quantity’ } df_en = df_jp.rename(columns=column_mapping) print(“\n=== 日本語→英語 ===”) print(df_en)

1-5. カラムの順序を変更する

# ===== カラムの並び替え ===== import pandas as pd df = pd.DataFrame({ ‘C’: [7, 8, 9], ‘A’: [1, 2, 3], ‘B’: [4, 5, 6] }) print(“=== 元のデータ(C, A, B の順)===”) print(df) # 方法1: 希望の順序でカラムを指定 df1 = df[[‘A’, ‘B’, ‘C’]] print(“\n=== A, B, C の順に並び替え ===”) print(df1) # 方法2: 特定のカラムを先頭に移動 cols = [‘B’] + [col for col in df.columns if col != ‘B’] df2 = df[cols] print(“\n=== B を先頭に移動 ===”) print(df2) # 方法3: アルファベット順にソート df3 = df[sorted(df.columns)] print(“\n=== アルファベット順 ===”) print(df3)

1-6. 条件に基づいてカラムの値を変更する

データ分析では、条件に基づいて値を変更することが頻繁にあります。

# ===== 条件付きでデータを変更 ===== import pandas as pd import numpy as np df = pd.DataFrame({ ‘name’: [‘田中’, ‘佐藤’, ‘鈴木’, ‘山田’, ‘高橋’], ‘age’: [15, 25, 35, 45, 65], ‘price’: [1000, 1500, 2000, 2500, 3000] }) print(“=== 元のデータ ===”) print(df) # 方法1: loc[]を使う(条件に一致する行を変更) df[‘category’] = ” # 空のカラムを作成 df.loc[df[‘age’] < 20, 'category'] = '未成年' df.loc[(df['age'] >= 20) & (df[‘age’] < 60), 'category'] = '成人' df.loc[df['age'] >= 60, ‘category’] = ‘シニア’ print(“\n=== loc[]で分類後 ===”) print(df) # 方法2: np.where()を使う(三項演算子のように使える) df[‘discount’] = np.where(df[‘price’] >= 2000, 0.1, 0) print(“\n=== np.where()で割引率設定後 ===”) print(df)
【実行結果】 === loc[]で分類後 === name age price category 0 田中 15 1000 未成年 1 佐藤 25 1500 成人 2 鈴木 35 2000 成人 3 山田 45 2500 成人 4 高橋 65 3000 シニア === np.where()で割引率設定後 === name age price category discount 0 田中 15 1000 未成年 0.0 1 佐藤 25 1500 成人 0.0 2 鈴木 35 2000 成人 0.1 3 山田 45 2500 成人 0.1 4 高橋 65 3000 シニア 0.1

1-7. np.select()で複数条件を処理

# ===== np.select()で複数条件を一度に処理 ===== import pandas as pd import numpy as np df = pd.DataFrame({ ‘score’: [95, 82, 68, 45, 30] }) print(“=== 元のデータ ===”) print(df) # 複数条件をリストで定義 conditions = [ df[‘score’] >= 90, # 条件1: 90点以上 (df[‘score’] >= 70) & (df[‘score’] < 90), # 条件2: 70-89点 (df['score'] >= 50) & (df[‘score’] < 70), # 条件3: 50-69点 df['score'] < 50 # 条件4: 50点未満 ] # 各条件に対応する値 choices = ['A', 'B', 'C', 'D'] # np.select()で一度に処理 df['grade'] = np.select(conditions, choices, default='不明') print("\n=== 成績ランク追加後 ===") print(df)
【実行結果】 === 成績ランク追加後 === score grade 0 95 A 1 82 B 2 68 C 3 45 D 4 30 D
条件分岐メソッドの比較
メソッド 条件数 使いどころ
loc[] 1つずつ シンプルな条件分岐、直感的でわかりやすい
np.where() 2択 True/Falseで値を分ける場合
np.select() 複数 3つ以上の条件分岐を一度に処理

✂️ 2. 文字列操作

2-1. 文字列メソッドの基本(.str)

Pandasでは、.strを使ってSeries全体に文字列操作を適用できます。

# ===== 基本的な文字列操作 ===== import pandas as pd df = pd.DataFrame({ ‘name’: [‘ 山田太郎 ‘, ‘SATO HANAKO’, ‘鈴木 一郎’, ‘tanaka-mika’] }) print(“=== 元のデータ ===”) print(df) # 1. 前後の空白を削除 df[‘strip’] = df[‘name’].str.strip() # 2. 小文字に変換 df[‘lower’] = df[‘name’].str.lower() # 3. 大文字に変換 df[‘upper’] = df[‘name’].str.upper() # 4. 文字数を取得 df[‘length’] = df[‘name’].str.len() # 5. 特定の文字を含むか判定 df[‘has_space’] = df[‘name’].str.contains(‘ ‘) print(“\n=== 文字列操作後 ===”) print(df)
主な文字列メソッド一覧
メソッド 説明
.str.strip() 前後の空白を削除 ‘ hello ‘ → ‘hello’
.str.lower() 小文字に変換 ‘HELLO’ → ‘hello’
.str.upper() 大文字に変換 ‘hello’ → ‘HELLO’
.str.len() 文字数を取得 ‘hello’ → 5
.str.replace() 文字を置換 ‘a-b-c’ → ‘a_b_c’
.str.split() 文字で分割 ‘a,b,c’ → [‘a’,’b’,’c’]

2-2. 文字列の分割(split)

# ===== splitで文字列を分割 ===== import pandas as pd df = pd.DataFrame({ ‘full_name’: [‘山田 太郎’, ‘佐藤 花子’, ‘鈴木 一郎’] }) print(“=== 元のデータ ===”) print(df) # 方法1: splitしてリストに df[‘name_list’] = df[‘full_name’].str.split(‘ ‘) print(“\n=== リストとして取得 ===”) print(df) # 方法2: splitして新しいカラムに展開(expand=True) df[[‘last_name’, ‘first_name’]] = df[‘full_name’].str.split(‘ ‘, expand=True) print(“\n=== 新しいカラムに展開 ===”) print(df) # メールアドレスを@で分割 df2 = pd.DataFrame({ ‘email’: [‘yamada@example.com’, ‘sato@test.jp’, ‘suzuki@company.co.jp’] }) df2[[‘user’, ‘domain’]] = df2[‘email’].str.split(‘@’, expand=True) print(“\n=== メールアドレスの分割 ===”) print(df2)
【実行結果】 === 新しいカラムに展開 === full_name name_list last_name first_name 0 山田 太郎 [山田, 太郎] 山田 太郎 1 佐藤 花子 [佐藤, 花子] 佐藤 花子 2 鈴木 一郎 [鈴木, 一郎] 鈴木 一郎 === メールアドレスの分割 === email user domain 0 yamada@example.com yamada example.com 1 sato@test.jp sato test.jp 2 suzuki@company.co.jp suzuki company.co.jp

2-3. 文字列の置換(replace)

# ===== replaceで文字列を置換 ===== import pandas as pd df = pd.DataFrame({ ‘phone’: [’03-1234-5678′, ‘090-9876-5432′, ’06-5555-6666’] }) print(“=== 元のデータ ===”) print(df) # ハイフンを削除 df[‘phone_clean’] = df[‘phone’].str.replace(‘-‘, ”) # 正規表現で複数の文字を削除(regex=True) df[‘phone_numbers’] = df[‘phone’].str.replace(r'[-()]’, ”, regex=True) print(“\n=== ハイフン削除後 ===”) print(df) # 複数の置換をチェーンで実行 df2 = pd.DataFrame({ ‘text’: [‘Hello World’, ‘Good Morning’, ‘Nice Day’] }) df2[‘text_ja’] = df2[‘text’].str.replace(‘Hello’, ‘こんにちは’)\ .str.replace(‘World’, ‘世界’)\ .str.replace(‘Good’, ‘良い’)\ .str.replace(‘Morning’, ‘朝’) print(“\n=== 複数置換 ===”) print(df2)

2-4. 文字列の検索と抽出(contains、extract)

# ===== 文字列の検索と抽出 ===== import pandas as pd df = pd.DataFrame({ ‘product’: [‘ノートPC Core i5’, ‘マウス Bluetooth’, ‘キーボード 無線’, ‘モニター 24インチ’] }) print(“=== 元のデータ ===”) print(df) # 1. 特定の文字列を含むか判定(contains) df[‘has_wireless’] = df[‘product’].str.contains(‘無線|Bluetooth’) # 2. 数値を含むか判定(正規表現) df[‘has_number’] = df[‘product’].str.contains(r’\d+’) # 3. 数値を抽出(extract) df[‘number’] = df[‘product’].str.extract(r'(\d+)’, expand=False) # 4. 先頭の単語を抽出 df[‘category’] = df[‘product’].str.extract(r’^(\S+)’, expand=False) print(“\n=== 検索・抽出後 ===”) print(df)
【実行結果】 === 検索・抽出後 === product has_wireless has_number number category 0 ノートPC Core i5 False True 5 ノートPC 1 マウス Bluetooth True False None マウス 2 キーボード 無線 True False None キーボード 3 モニター 24インチ False True 24 モニター

2-5. 実践例:住所データの分割

# ===== 住所データの処理 ===== import pandas as pd df = pd.DataFrame({ ‘address’: [ ‘東京都渋谷区渋谷1-2-3’, ‘大阪府大阪市北区梅田4-5-6’, ‘福岡県福岡市博多区博多駅前7-8-9’ ] }) print(“=== 元のデータ ===”) print(df) # 都道府県を抽出(2〜3文字 + 都道府県) df[‘prefecture’] = df[‘address’].str.extract(r'(.{2,3}[都道府県])’, expand=False) # 市区町村を抽出 df[‘city’] = df[‘address’].str.extract(r'[都道府県](.+?[市区町村])’, expand=False) # 番地を抽出 df[‘block’] = df[‘address’].str.extract(r'(\d+-\d+-\d+)’, expand=False) print(“\n=== 住所分割後 ===”) print(df) # 郵便番号の抽出例 df2 = pd.DataFrame({ ‘text’: [‘郵便番号は123-4567です’, ‘〒100-0001に送付してください’] }) df2[‘zipcode’] = df2[‘text’].str.extract(r'(\d{3}-\d{4})’, expand=False) print(“\n=== 郵便番号抽出 ===”) print(df2)

📅 3. 日付データの処理

3-1. 日付型への変換

文字列で格納された日付は、pd.to_datetime()で日付型に変換します。

# ===== 日付型への変換 ===== import pandas as pd df = pd.DataFrame({ ‘date_str’: [‘2024-01-01’, ‘2024-01-02’, ‘2024-01-03’] }) print(“=== 元のデータ(文字列型)===”) print(df) print(f”データ型: {df[‘date_str’].dtype}”) # 文字列 → 日付型に変換 df[‘date’] = pd.to_datetime(df[‘date_str’]) print(“\n=== 変換後(日付型)===”) print(df) print(f”データ型: {df[‘date’].dtype}”)

3-2. 様々な日付形式の変換

# ===== 様々な日付形式の変換 ===== import pandas as pd df = pd.DataFrame({ ‘format1’: [‘2024/01/01’, ‘2024/01/02’], ‘format2′: [’01-Jan-2024′, ’02-Jan-2024’], ‘format3’: [‘2024年1月1日’, ‘2024年1月2日’], ‘format4’: [‘20240101’, ‘20240102’] }) print(“=== 元のデータ ===”) print(df) # 自動認識(スラッシュ区切り) df[‘date1’] = pd.to_datetime(df[‘format1’]) # format指定(英語の月名) df[‘date2’] = pd.to_datetime(df[‘format2′], format=’%d-%b-%Y’) # format指定(日本語) df[‘date3’] = pd.to_datetime(df[‘format3′], format=’%Y年%m月%d日’) # format指定(区切りなし) df[‘date4’] = pd.to_datetime(df[‘format4′], format=’%Y%m%d’) print(“\n=== 変換後 ===”) print(df[[‘date1’, ‘date2’, ‘date3’, ‘date4’]])
日付フォーマットコード一覧
コード 意味
%Y 4桁の年 2024
%m 2桁の月(01-12) 01, 12
%d 2桁の日(01-31) 01, 31
%H 24時間制の時(00-23) 09, 23
%M 分(00-59) 30, 59
%S 秒(00-59) 00, 59
%b 英語の月名(短縮) Jan, Dec

3-3. 日付から要素を抽出(.dt)

# ===== 日付の要素を取得 ===== import pandas as pd df = pd.DataFrame({ ‘date’: pd.to_datetime([‘2024-01-15’, ‘2024-02-20’, ‘2024-03-25’]) }) print(“=== 元のデータ ===”) print(df) # 年・月・日を抽出 df[‘year’] = df[‘date’].dt.year df[‘month’] = df[‘date’].dt.month df[‘day’] = df[‘date’].dt.day # 曜日を取得(0=月曜, 6=日曜) df[‘dayofweek’] = df[‘date’].dt.dayofweek # 曜日名を取得(英語) df[‘day_name’] = df[‘date’].dt.day_name() # 年月を取得(集計用) df[‘year_month’] = df[‘date’].dt.to_period(‘M’) # 四半期を取得 df[‘quarter’] = df[‘date’].dt.quarter print(“\n=== 要素抽出後 ===”) print(df)
【実行結果】 === 要素抽出後 === date year month day dayofweek day_name year_month quarter 0 2024-01-15 2024 1 15 0 Monday 2024-01 1 1 2024-02-20 2024 2 20 1 Tuesday 2024-02 1 2 2024-03-25 2024 3 25 0 Monday 2024-03 1

3-4. 日付の計算

# ===== 日付の加算・減算 ===== import pandas as pd df = pd.DataFrame({ ‘order_date’: pd.to_datetime([‘2024-01-01’, ‘2024-01-15’, ‘2024-02-01’]) }) print(“=== 元のデータ ===”) print(df) # 日付に日数を加算 df[‘delivery_date’] = df[‘order_date’] + pd.Timedelta(days=3) # 日付に月を加算 df[‘next_month’] = df[‘order_date’] + pd.DateOffset(months=1) # 日付の差を計算(日数) df[‘days_diff’] = (df[‘delivery_date’] – df[‘order_date’]).dt.days # 今日との差を計算 df[‘days_from_today’] = (pd.Timestamp.now() – df[‘order_date’]).dt.days print(“\n=== 日付計算後 ===”) print(df)

3-5. 日付でフィルタリング

# ===== 日付でデータを絞り込む ===== import pandas as pd df = pd.DataFrame({ ‘order_date’: pd.to_datetime([ ‘2024-01-01’, ‘2024-01-15’, ‘2024-02-01’, ‘2024-02-15’, ‘2024-03-01’ ]), ‘amount’: [10000, 15000, 20000, 18000, 22000] }) print(“=== 元のデータ ===”) print(df) # 1月のデータを抽出 jan_data = df[(df[‘order_date’] >= ‘2024-01-01’) & (df[‘order_date’] < '2024-02-01')] print("\n=== 1月のデータ ===") print(jan_data) # 特定の期間(1/15〜2/15) period_data = df[(df['order_date'] >= ‘2024-01-15’) & (df[‘order_date’] <= '2024-02-15')] print("\n=== 1/15〜2/15のデータ ===") print(period_data) # 月でフィルタ(.dt.monthを使う) feb_data = df[df['order_date'].dt.month == 2] print("\n=== 2月のデータ(.dt.month使用)===") print(feb_data)

3-6. 実践例:売上データの日付処理

# ===== 実践的な日付処理 ===== import pandas as pd df = pd.DataFrame({ ‘order_id’: [1, 2, 3, 4, 5], ‘order_date’: [‘2024-01-15 14:30:00’, ‘2024-01-16 09:15:00’, ‘2024-02-01 18:45:00’, ‘2024-02-15 11:20:00’, ‘2024-03-01 16:10:00’], ‘amount’: [10000, 15000, 20000, 18000, 22000] }) # 日付型に変換 df[‘order_date’] = pd.to_datetime(df[‘order_date’]) # 年月を追加(集計用) df[‘year_month’] = df[‘order_date’].dt.to_period(‘M’) # 曜日を追加(日本語) weekday_ja = {0: ‘月’, 1: ‘火’, 2: ‘水’, 3: ‘木’, 4: ‘金’, 5: ‘土’, 6: ‘日’} df[‘weekday’] = df[‘order_date’].dt.dayofweek.map(weekday_ja) # 時間帯を分類 df[‘time_period’] = pd.cut( df[‘order_date’].dt.hour, bins=[0, 6, 12, 18, 24], labels=[‘深夜’, ‘午前’, ‘午後’, ‘夜間’], right=False ) print(“=== 日付処理後 ===”) print(df) # 月ごとの売上集計 monthly_sales = df.groupby(‘year_month’)[‘amount’].sum() print(“\n=== 月別売上 ===”) print(monthly_sales)

🏷️ 4. カテゴリデータの変換

4-1. カテゴリ型とは?

カテゴリ型は、限られた値を持つデータ(性別、都道府県、ランクなど)を効率的に扱うデータ型です。

✅ カテゴリ型のメリット
  • メモリ節約:文字列を数値コードで管理するため、メモリ使用量が減る
  • 処理速度向上:内部的に数値で管理するため、比較が高速
  • 順序の指定:S < M < L のような順序を定義できる
# ===== カテゴリ型への変換 ===== import pandas as pd df = pd.DataFrame({ ‘gender’: [‘男’, ‘女’, ‘男’, ‘女’, ‘男’] * 1000, # 5000行 ‘city’: [‘東京’, ‘大阪’, ‘東京’, ‘福岡’, ‘大阪’] * 1000 }) print(“=== 変換前 ===”) print(f”データ型: {df.dtypes}”) print(f”メモリ: {df.memory_usage(deep=True).sum():,} bytes”) # カテゴリ型に変換 df[‘gender’] = df[‘gender’].astype(‘category’) df[‘city’] = df[‘city’].astype(‘category’) print(“\n=== 変換後 ===”) print(f”データ型: {df.dtypes}”) print(f”メモリ: {df.memory_usage(deep=True).sum():,} bytes”)
【実行結果】 === 変換前 === メモリ: 580,128 bytes === 変換後 === メモリ: 20,416 bytes → 約96%のメモリ削減!

4-2. ラベルエンコーディング

ラベルエンコーディングは、カテゴリを数値(0, 1, 2…)に変換する方法です。

# ===== ラベルエンコーディング ===== import pandas as pd df = pd.DataFrame({ ‘size’: [‘S’, ‘M’, ‘L’, ‘M’, ‘S’, ‘XL’] }) print(“=== 元のデータ ===”) print(df) # 方法1: カテゴリコードを使う df[‘size_cat’] = df[‘size’].astype(‘category’) df[‘size_code’] = df[‘size_cat’].cat.codes print(“\n=== cat.codesでエンコード ===”) print(df) # 方法2: mapで手動変換(順序を明示的に指定) size_mapping = {‘S’: 0, ‘M’: 1, ‘L’: 2, ‘XL’: 3} df[‘size_mapped’] = df[‘size’].map(size_mapping) print(“\n=== mapで手動エンコード ===”) print(df) # 方法3: sklearn の LabelEncoder from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df[‘size_sklearn’] = le.fit_transform(df[‘size’]) print(“\n=== LabelEncoderでエンコード ===”) print(df) print(f”\nラベル一覧: {le.classes_}”)

4-3. ワンホットエンコーディング

ワンホットエンコーディングは、カテゴリをダミー変数(0と1)に変換する方法です。
機械学習で最もよく使われます。

# ===== ワンホットエンコーディング ===== import pandas as pd df = pd.DataFrame({ ‘color’: [‘赤’, ‘青’, ‘緑’, ‘赤’, ‘青’] }) print(“=== 元のデータ ===”) print(df) # 方法1: pd.get_dummies() dummies = pd.get_dummies(df[‘color’], prefix=’color’) print(“\n=== ワンホットエンコーディング ===”) print(dummies) # DataFrameに結合 df_with_dummies = pd.concat([df, dummies], axis=1) print(“\n=== 元のDataFrameに結合 ===”) print(df_with_dummies) # 方法2: drop_first=True(多重共線性を回避) dummies_dropped = pd.get_dummies(df[‘color’], prefix=’color’, drop_first=True) print(“\n=== drop_first=True(1列削除)===”) print(dummies_dropped)
【実行結果】 === ワンホットエンコーディング === color_緑 color_赤 color_青 0 False True False 1 False False True 2 True False False 3 False True False 4 False False True === drop_first=True(1列削除)=== color_赤 color_青 0 True False 1 False True 2 False False 3 True False 4 False True
⚠️ drop_first=True の意味

3つのカテゴリ(赤、青、緑)がある場合、2つの列(赤、青)があれば緑は判断できます。
(赤=0, 青=0 なら緑)
この冗長性を多重共線性といい、機械学習で問題になることがあります。
drop_first=Trueでこれを回避できます。

4-4. 順序付きカテゴリ

# ===== 順序のあるカテゴリデータ ===== import pandas as pd df = pd.DataFrame({ ‘grade’: [‘A’, ‘B’, ‘C’, ‘A’, ‘B’, ‘C’, ‘A’] }) print(“=== 元のデータ ===”) print(df) # 順序を指定してカテゴリ化 df[‘grade_cat’] = pd.Categorical( df[‘grade’], categories=[‘C’, ‘B’, ‘A’], # C < B < A の順序 ordered=True ) # 順序通りに並び替え df_sorted = df.sort_values('grade_cat') print("\n=== 順序付きカテゴリでソート ===") print(df_sorted) # 比較演算が可能 df['is_good'] = df['grade_cat'] >= ‘B’ print(“\n=== B以上かどうか ===”) print(df)

4-5. 実践例:アンケートデータの変換

# ===== 実践的なカテゴリ変換 ===== import pandas as pd df = pd.DataFrame({ ‘satisfaction’: [‘非常に満足’, ‘満足’, ‘普通’, ‘不満’, ‘非常に不満’], ‘age_group’: [’20代’, ’30代’, ’20代’, ’40代’, ’30代’] }) print(“=== 元のデータ ===”) print(df) # 満足度を数値に変換(順序を考慮) satisfaction_mapping = { ‘非常に不満’: 1, ‘不満’: 2, ‘普通’: 3, ‘満足’: 4, ‘非常に満足’: 5 } df[‘satisfaction_score’] = df[‘satisfaction’].map(satisfaction_mapping) # 年代をワンホットエンコーディング age_dummies = pd.get_dummies(df[‘age_group’], prefix=’age’) df = pd.concat([df, age_dummies], axis=1) print(“\n=== 変換後 ===”) print(df) # 平均満足度を計算 print(f”\n平均満足度: {df[‘satisfaction_score’].mean():.2f}”)

📝 STEP 9 のまとめ

✅ このステップで学んだこと
  • カラム操作:追加(直接代入、assign)、削除(drop、del)、名前変更(rename)
  • 条件分岐:loc[]、np.where()、np.select()
  • 文字列操作:strip()、split()、replace()、contains()、extract()
  • 日付処理:to_datetime()、.dt.year/.dt.month、日付計算
  • カテゴリ変換:astype(‘category’)、ラベルエンコーディング、ワンホットエンコーディング
💡 データ変換のベストプラクティス
  1. 元データを残す:変換前のカラムは削除せず残しておく
  2. カラム名をわかりやすく:_normalized、_encoded など接尾辞をつける
  3. 処理の順序を考える:依存関係のある処理は順番に
  4. 変換後に確認:必ずhead()やdescribe()で確認
  5. エラーハンドリング:変換できない値がある場合を想定
🎯 次のステップの予告

次のSTEP 10では、「データ結合とマージ」を学びます。

  • merge()(SQLのJOINと同様)
  • concat()(縦横連結)
  • join()(インデックスベース結合)
  • 複数テーブルの結合戦略

📝 練習問題

問題 1 基礎

priceとquantityを掛け算してtotalカラムを追加してください。

【解答例】
df[‘total’] = df[‘price’] * df[‘quantity’]
問題 2 基礎

nameカラムの前後の空白を削除してください。

【解答例】
df[‘name’] = df[‘name’].str.strip()
問題 3 基礎

カラム名 ‘old_col’ を ‘new_col’ に変更してください。

【解答例】
df = df.rename(columns={‘old_col’: ‘new_col’})
問題 4 基礎

dateカラムを日付型に変換してください。

【解答例】
df[‘date’] = pd.to_datetime(df[‘date’])
問題 5 基礎

phoneカラムからハイフンを削除してください。

【解答例】
df[‘phone’] = df[‘phone’].str.replace(‘-‘, ”)
問題 6 基礎

不要なカラム ‘temp_col’ を削除してください。

【解答例】
df = df.drop(‘temp_col’, axis=1) # または df.drop(‘temp_col’, axis=1, inplace=True)
問題 7 応用

order_dateから年と月を抽出して、それぞれyear、monthカラムに追加してください。

【解答例】
df[‘order_date’] = pd.to_datetime(df[‘order_date’]) df[‘year’] = df[‘order_date’].dt.year df[‘month’] = df[‘order_date’].dt.month
問題 8 応用

full_nameカラムをスペースで分割して、last_nameとfirst_nameカラムに分けてください。

【解答例】
df[[‘last_name’, ‘first_name’]] = df[‘full_name’].str.split(‘ ‘, expand=True)
問題 9 応用

categoryカラムをワンホットエンコーディングしてください。

【解答例】
dummies = pd.get_dummies(df[‘category’], prefix=’cat’) df = pd.concat([df, dummies], axis=1)
問題 10 応用

ageカラムの値に基づいて、20歳未満を’未成年’、20歳以上を’成人’としてage_categoryカラムを作成してください(np.where使用)。

【解答例】
import numpy as np df[‘age_category’] = np.where(df[‘age’] < 20, '未成年', '成人')
問題 11 応用

emailカラムから@より前のユーザー名を抽出してusernameカラムに格納してください。

【解答例】
df[‘username’] = df[‘email’].str.split(‘@’).str[0] # または df[‘username’] = df[‘email’].str.extract(r’^([^@]+)’, expand=False)
問題 12 応用

order_dateに3日を加算してdelivery_dateカラムを作成してください。

【解答例】
df[‘order_date’] = pd.to_datetime(df[‘order_date’]) df[‘delivery_date’] = df[‘order_date’] + pd.Timedelta(days=3)
問題 13 発展

scoreカラムの値に基づいて、90以上を’A’、70以上を’B’、50以上を’C’、50未満を’D’としてgradeカラムを作成してください(np.select使用)。

【解答例】
import numpy as np conditions = [ df[‘score’] >= 90, df[‘score’] >= 70, df[‘score’] >= 50, df[‘score’] < 50 ] choices = ['A', 'B', 'C', 'D'] df['grade'] = np.select(conditions, choices)
問題 14 発展

addressカラムから都道府県を抽出してprefectureカラムに格納してください(正規表現使用)。

【解答例】
df[‘prefecture’] = df[‘address’].str.extract(r'(.{2,3}[都道府県])’, expand=False)
問題 15 発展

以下の変換を一度に行ってください:
① dateカラムを日付型に変換
② yearとmonthを抽出
③ priceとquantityからtotalを計算
④ categoryをワンホットエンコーディング

【解答例】
import pandas as pd # ① 日付型に変換 df[‘date’] = pd.to_datetime(df[‘date’]) # ② year と month を抽出 df[‘year’] = df[‘date’].dt.year df[‘month’] = df[‘date’].dt.month # ③ total を計算 df[‘total’] = df[‘price’] * df[‘quantity’] # ④ category をワンホットエンコーディング dummies = pd.get_dummies(df[‘category’], prefix=’cat’) df = pd.concat([df, dummies], axis=1) print(df)

📝

学習メモ

ETL・データパイプライン構築 - Step 9

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