Python辞書のキー名を変更する方法完全ガイド:効率的なリネーム・置換テクニック
Python辞書を扱う際、「キー名を変更したい」という場面は頻繁に発生します。APIの仕様変更、データベースカラム名の変更、日本語キーの英語化など、様々なケースで辞書のキー名変更が必要になります。本記事では、辞書のキー名を安全かつ効率的に変更する方法を、実践的なサンプルコードとともに詳しく解説します。
基本的なキー名変更方法
pop()とセットを使った標準的な方法
最も一般的で安全な方法です。
user_data = {'old_name': '太郎', 'age': 25, 'city': '東京'}
# キー名を変更
user_data['new_name'] = user_data.pop('old_name')
print(user_data) # {'age': 25, 'city': '東京', 'new_name': '太郎'}
del文を使った方法
user_data = {'old_key': 'value', 'age': 25}
# 値を保存してからキーを削除
value = user_data['old_key']
del user_data['old_key']
user_data['new_key'] = value
print(user_data) # {'age': 25, 'new_key': 'value'}
存在チェック付きの安全な変更
def rename_key(dictionary, old_key, new_key):
"""安全なキー名変更"""
if old_key in dictionary:
dictionary[new_key] = dictionary.pop(old_key)
return True
return False
user_data = {'name': '太郎', 'age': 25}
success = rename_key(user_data, 'name', 'username')
print(f"変更成功: {success}") # True
print(user_data) # {'age': 25, 'username': '太郎'}
複数キーの一括変更
辞書を使ったマッピング変更
original_data = {
'fname': '太郎',
'lname': '田中',
'yrs': 25,
'loc': '東京'
}
# キー変更マッピング
key_mapping = {
'fname': 'first_name',
'lname': 'last_name',
'yrs': 'age',
'loc': 'location'
}
# 一括変更
for old_key, new_key in key_mapping.items():
if old_key in original_data:
original_data[new_key] = original_data.pop(old_key)
print(original_data)
# {'first_name': '太郎', 'last_name': '田中', 'age': 25, 'location': '東京'}
関数化した一括変更
def rename_keys(dictionary, mapping):
"""複数キーを一括変更"""
for old_key, new_key in mapping.items():
if old_key in dictionary:
dictionary[new_key] = dictionary.pop(old_key)
return dictionary
data = {'a': 1, 'b': 2, 'c': 3}
mapping = {'a': 'alpha', 'b': 'beta', 'c': 'gamma'}
result = rename_keys(data, mapping)
print(result) # {'alpha': 1, 'beta': 2, 'gamma': 3}
リスト内包表記を使った新しい辞書作成
original = {'old_key1': 'value1', 'old_key2': 'value2', 'keep': 'value3'}
key_mapping = {'old_key1': 'new_key1', 'old_key2': 'new_key2'}
# 新しい辞書を作成
new_dict = {
key_mapping.get(k, k): v
for k, v in original.items()
}
print(new_dict) # {'new_key1': 'value1', 'new_key2': 'value2', 'keep': 'value3'}
条件付きキー名変更
パターンマッチングによる変更
import re
api_data = {
'user_name': '太郎',
'user_age': 25,
'user_email': 'taro@example.com',
'product_id': 123
}
# プレフィックスを削除
def remove_prefix(dictionary, prefix):
new_dict = {}
for key, value in dictionary.items():
if key.startswith(prefix):
new_key = key[len(prefix):]
new_dict[new_key] = value
else:
new_dict[key] = value
return new_dict
cleaned_data = remove_prefix(api_data, 'user_')
print(cleaned_data)
# {'name': '太郎', 'age': 25, 'email': 'taro@example.com', 'product_id': 123}
正規表現を使った高度な変更
import re
data = {
'firstName': '太郎',
'lastName': '田中',
'phoneNumber': '090-1234-5678',
'emailAddress': 'taro@example.com'
}
def camel_to_snake(dictionary):
"""キャメルケースをスネークケースに変更"""
new_dict = {}
for key, value in dictionary.items():
# キャメルケースをスネークケースに変換
snake_key = re.sub('([A-Z])', r'_\1', key).lower().lstrip('_')
new_dict[snake_key] = value
return new_dict
result = camel_to_snake(data)
print(result)
# {'first_name': '太郎', 'last_name': '田中', 'phone_number': '090-1234-5678', 'email_address': 'taro@example.com'}
値に基づくキー変更
grades = {
'student_001': 85,
'student_002': 92,
'student_003': 76,
'student_004': 94
}
# 成績に基づいてキーを変更
def rename_by_grade(dictionary):
new_dict = {}
for key, grade in dictionary.items():
if grade >= 90:
new_key = key.replace('student', 'excellent_student')
elif grade >= 80:
new_key = key.replace('student', 'good_student')
else:
new_key = key.replace('student', 'average_student')
new_dict[new_key] = grade
return new_dict
result = rename_by_grade(grades)
print(result)
# {'good_student_001': 85, 'excellent_student_002': 92, 'average_student_003': 76, 'excellent_student_004': 94}
実践的な応用例
APIレスポンスのキー正規化
api_response = {
'UserID': 123,
'user-name': '太郎',
'User_Email': 'taro@example.com',
'phone_number': '090-1234-5678'
}
def normalize_keys(dictionary):
"""キーを統一形式に正規化"""
normalized = {}
for key, value in dictionary.items():
# 全て小文字のスネークケースに統一
normalized_key = re.sub(r'[-\s]+', '_', key) # ハイフンとスペースをアンダースコアに
normalized_key = re.sub('([A-Z])', r'_\1', normalized_key).lower() # キャメルケースを変換
normalized_key = normalized_key.strip('_') # 前後のアンダースコア削除
normalized[normalized_key] = value
return normalized
result = normalize_keys(api_response)
print(result)
# {'user_i_d': 123, 'user_name': '太郎', 'user_email': 'taro@example.com', 'phone_number': '090-1234-5678'}
データベースマッピングでの活用
db_record = {
'id': 1,
'created_at': '2024-01-01',
'updated_at': '2024-01-02',
'user_name': '太郎',
'user_status': 'active'
}
# データベースカラム名をアプリケーション用に変換
db_to_app_mapping = {
'created_at': 'createdDate',
'updated_at': 'updatedDate',
'user_name': 'userName',
'user_status': 'status'
}
def convert_db_to_app(record, mapping):
"""DB形式からアプリ形式に変換"""
converted = {}
for key, value in record.items():
new_key = mapping.get(key, key)
converted[new_key] = value
return converted
app_data = convert_db_to_app(db_record, db_to_app_mapping)
print(app_data)
# {'id': 1, 'createdDate': '2024-01-01', 'updatedDate': '2024-01-02', 'userName': '太郎', 'status': 'active'}
CSVヘッダーの正規化
csv_data = {
'名前': '太郎',
'年齢': 25,
'メール アドレス': 'taro@example.com',
'電話番号(携帯)': '090-1234-5678'
}
# 日本語ヘッダーを英語に変換
header_mapping = {
'名前': 'name',
'年齢': 'age',
'メール アドレス': 'email',
'電話番号(携帯)': 'mobile_phone'
}
def localize_headers(data, mapping):
"""ヘッダーを英語化"""
result = {}
for key, value in data.items():
english_key = mapping.get(key, key)
result[english_key] = value
return result
english_data = localize_headers(csv_data, header_mapping)
print(english_data)
# {'name': '太郎', 'age': 25, 'email': 'taro@example.com', 'mobile_phone': '090-1234-5678'}
ネストした辞書でのキー変更
深い階層のキー変更
nested_data = {
'user_info': {
'personal': {
'old_name': '太郎',
'old_age': 25
},
'contact': {
'old_email': 'taro@example.com'
}
}
}
def rename_nested_keys(data, old_key, new_key):
"""ネストした辞書内のキーを再帰的に変更"""
if isinstance(data, dict):
new_data = {}
for k, v in data.items():
# キー名を変更
new_k = new_key if k == old_key else k
# 値が辞書の場合は再帰的に処理
new_data[new_k] = rename_nested_keys(v, old_key, new_key)
return new_data
return data
# 全ての'old_name'を'name'に変更
result = rename_nested_keys(nested_data, 'old_name', 'name')
print(result)
複数レベルでの一括変更
complex_data = {
'level1': {
'oldKey1': 'value1',
'level2': {
'oldKey2': 'value2',
'oldKey3': 'value3'
}
}
}
def bulk_rename_nested(data, mapping):
"""ネストした辞書で複数キーを一括変更"""
if isinstance(data, dict):
new_data = {}
for key, value in data.items():
new_key = mapping.get(key, key)
new_data[new_key] = bulk_rename_nested(value, mapping)
return new_data
return data
key_changes = {
'oldKey1': 'newKey1',
'oldKey2': 'newKey2',
'oldKey3': 'newKey3'
}
result = bulk_rename_nested(complex_data, key_changes)
print(result)
パフォーマンス比較
各手法の速度比較
import timeit
# テストデータの準備
large_dict = {f'old_key_{i}': i for i in range(10000)}
mapping = {f'old_key_{i}': f'new_key_{i}' for i in range(10000)}
# 方法1: pop()を使用
def method1(data, mapping):
for old_key, new_key in mapping.items():
if old_key in data:
data[new_key] = data.pop(old_key)
# 方法2: 新しい辞書を作成
def method2(data, mapping):
return {mapping.get(k, k): v for k, v in data.items()}
# 方法3: del文を使用
def method3(data, mapping):
for old_key, new_key in mapping.items():
if old_key in data:
value = data[old_key]
del data[old_key]
data[new_key] = value
# パフォーマンステスト(小規模データで実行)
small_dict = {f'old_{i}': i for i in range(100)}
small_mapping = {f'old_{i}': f'new_{i}' for i in range(100)}
time1 = timeit.timeit(lambda: method1(small_dict.copy(), small_mapping), number=1000)
time2 = timeit.timeit(lambda: method2(small_dict, small_mapping), number=1000)
print(f"pop()方式: {time1:.4f}秒")
print(f"新辞書作成: {time2:.4f}秒")
エラーハンドリングとベストプラクティス
安全なキー変更の実装
def safe_rename_key(dictionary, old_key, new_key, overwrite=False):
"""安全なキー名変更(エラーハンドリング付き)"""
# 入力チェック
if not isinstance(dictionary, dict):
raise TypeError("第一引数は辞書である必要があります")
# 元キーの存在チェック
if old_key not in dictionary:
return False, f"キー '{old_key}' が存在しません"
# 新キーの重複チェック
if new_key in dictionary and not overwrite:
return False, f"キー '{new_key}' は既に存在します"
# キー変更実行
try:
dictionary[new_key] = dictionary.pop(old_key)
return True, f"キー '{old_key}' を '{new_key}' に変更しました"
except Exception as e:
return False, f"変更中にエラー: {e}"
# 使用例
data = {'name': '太郎', 'age': 25}
success, message = safe_rename_key(data, 'name', 'username')
print(f"{message}") # キー 'name' を 'username' に変更しました
# 重複チェック
success, message = safe_rename_key(data, 'age', 'username')
print(f"{message}") # キー 'username' は既に存在します
バックアップ機能付きの変更
def rename_with_backup(dictionary, old_key, new_key):
"""バックアップ機能付きキー変更"""
# 元の辞書をバックアップ
backup = dictionary.copy()
try:
if old_key in dictionary:
dictionary[new_key] = dictionary.pop(old_key)
return True, backup
else:
return False, None
except Exception:
# エラー時は元の状態に戻す
dictionary.clear()
dictionary.update(backup)
return False, None
# 使用例
data = {'important_data': '重要な値'}
success, backup = rename_with_backup(data, 'important_data', 'crucial_data')
if success:
print("変更成功:", data)
else:
print("変更失敗、元の状態に復元:", data)
型安全な変更
from typing import Dict, Any, Optional, Tuple
def type_safe_rename(
dictionary: Dict[str, Any],
old_key: str,
new_key: str
) -> Tuple[bool, Optional[str]]:
"""型安全なキー名変更"""
if not all(isinstance(k, str) for k in [old_key, new_key]):
return False, "キー名は文字列である必要があります"
if old_key not in dictionary:
return False, f"キー '{old_key}' が見つかりません"
dictionary[new_key] = dictionary.pop(old_key)
return True, None
# 使用例
user_data: Dict[str, Any] = {'name': '太郎', 'age': 25}
success, error = type_safe_rename(user_data, 'name', 'username')
if success:
print("変更成功:", user_data)
else:
print("エラー:", error)
まとめ
Python辞書のキー名変更には、様々な方法とテクニックがあります。状況に応じて最適な方法を選択することが重要です。
基本的な変更手法
pop()メソッドが最も安全で推奨される方法del文も使えるが、pop()の方が簡潔
複数キー変更
- マッピング辞書を使った一括変更が効率的
- 新しい辞書作成は元の辞書を保持したい場合に有効
実用的なポイント
- エラーハンドリングを必ず実装
- 大量データではパフォーマンスを考慮
- 型チェックでバグを防止
注意すべき点
- キーの重複チェック
- ネストした辞書での再帰処理
- バックアップ機能の実装
これらの技術を適切に組み合わせることで、安全で効率的な辞書のキー名変更を実現できるでしょう。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座


