データ型【Pandas dtypeシステム完全ガイド】
データ型(dtype)は、Pandasがデータをどのように保存し、操作するかを決定します。正しいdtypeを選べば、コードの実行速度が10倍になり、メモリ使用量を80%削減できます。逆に間違った型を選ぶと、精度の損失、操作エラー、メモリの肥大化に直面することになります。このセクションでは、Pandasのdtypeシステムを一通り解説し、各型の特徴と変換方法、そして最も実用的なメモリ最適化テクニックを理解できるようにします。
⚠️ 注意: 以下のコードはローカルのPython環境で実行してください。
1. このセクションで学ぶこと
- ❶ PandasのdtypeシステムとNumPyのdtypeの違い
- ❷ object、StringDtype、categoryの使い分け
- ❸ astype / convert_dtypes / infer_objects による型変換
- ❹ Nullable型(Int64 / Float64 / boolean)
- ❺ メモリ最適化戦略(category / downcast)
2. ボブのメモリ肥大化危機
(1) 問題点:500 MBの顧客テーブル
ボブは顧客データセットをDataFrameに読み込み、メモリ使用量を確認したところ、500 MBもありました!10万行程度でこんなに多くのスペースを使うはずがありません:
PYTHON
import pandas as pd
# 顧客データの読み込み(シミュレーション)
df = pd.DataFrame({
'customer_id': range(100000),
'name': ['Customer_' + str(i) for i in range(100000)],
'city': ['New York', 'London', 'Tokyo', 'Paris', 'Sydney'] * 20000,
'age': [25 + i % 50 for i in range(100000)],
'loyalty_points': [100 + i * 10 for i in range(100000)]
})
print(f"最適化前のメモリ: {df.memory_usage(deep=True).sum() / 1024 / 1024:.1f} MB")
# 典型的な出力: ~18 MB(この例は小規模)
# 実際の10万行データセットで文字列カラムが多い場合、500 MB以上に達することがあります
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
原因はobject型です。デフォルトでは、Pandasは文字列カラムをobject(Pythonオブジェクトのポインタ)として保存します。各要素が完全なPython文字列オブジェクトであるため、メモリオーバーヘッドが非常に大きくなります。
(2) 解決策:category型による10倍の圧縮
▶ サンプル:categoryメモリ最適化
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:categoryメモリ最適化(難易度 ⭐⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'customer_id': range(100000),
'name': ['Customer_' + str(i) for i in range(100000)],
'city': ['New York', 'London', 'Tokyo', 'Paris', 'Sydney'] * 20000,
'age': [25 + i % 50 for i in range(100000)],
'loyalty_points': [100 + i * 10 for i in range(100000)]
})
# 最適化前のメモリを確認
mem_before = df.memory_usage(deep=True).sum() / 1024 / 1024
# 最適化:cityはユニーク値が5つのみ → category
df['city'] = df['city'].astype('category')
# 最適化:ageの範囲は25〜74 → int8で十分(最大127)
df['age'] = df['age'].astype('int8')
# 最適化:loyalty_pointsの範囲 → int32で十分
df['loyalty_points'] = df['loyalty_points'].astype('int32')
mem_after = df.memory_usage(deep=True).sum() / 1024 / 1024
print(f"最適化前: {mem_before:.1f} MB")
print(f"最適化後: {mem_after:.1f} MB")
print(f"削減率: {(1 - mem_after/mem_before)*100:.0f}%")
# 最適化前: ~18 MB
# 最適化後: ~5 MB
# 削減率: ~72%
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(3) 成果:3つの主要な最適化テクニック
| テクニック | 効果 | 適用場面 |
|---|---|---|
| object→category | 90%以上のメモリ削減 | 低カーディナリティの文字列(ユニーク値が行数の50%未満) |
| int64→int8/int16/int32 | 約75%のメモリ削減 | 数値範囲が小さい場合 |
| float64→float32 | 50%のメモリ削減 | 精度要件が低い場合 |
3. Pandasのdtypeシステム
(1) 型の全体像
graph TB
DT["Pandas dtype"] --> NUM["数値型"]
DT --> STR["文字列型"]
DT --> DT_TYPE["日時型"]
DT --> BOOL["ブール型"]
DT --> CAT["カテゴリ型"]
DT --> NULL["Nullable型"]
NUM --> I["int8/16/32/64"]
NUM --> UI["uint8/16/32/64"]
NUM --> F["float32/float64"]
STR --> O["object(レガシー)"]
STR --> SD["StringDtype(新仕様)"]
DT_TYPE --> DT64["datetime64[ns]"]
DT_TYPE --> TD64["timedelta64[ns]"]
BOOL --> PB["bool(NumPy)"]
BOOL --> NB["boolean(Nullable)"]
NULL --> NI["Int8/16/32/64"]
NULL --> NF["Float32/64"]
NULL --> NBO["boolean"]
NULL --> NS["string"]
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) PandasのdtypeとNumPyのdtypeの比較
| 機能 | NumPy dtype | Pandas dtype |
|---|---|---|
| 数値型 | int8〜64 / float32〜64 | NumPyと同じ + Nullable(Int64/Float64) |
| 文字列 | object | object / StringDtype / string |
| ブール型 | bool | bool / boolean(Nullable) |
| 欠損値 | np.nan(floatのみ) | NaN / NaT / pd.NA(完全対応) |
| カテゴリ | なし | category |
| 時間 | datetime64 | datetime64[ns] / timedelta64[ns] |
| 拡張 | なし | ExtensionDtype(カスタム) |
📌 ポイント: PandasのNullable型(大文字始まり:Int64 / Float64 / boolean / string)は、1.0で導入された機能です。
pd.NAを使用して欠損値を統一的に表現し、「整数カラムにNaNを保持できない」という長年の問題を解決します。
4. object vs StringDtype vs category
(1) 3つの型の比較
| 機能 | object | StringDtype | category |
|---|---|---|---|
| 内部ストレージ | Pythonオブジェクトのポインタ | 専用の文字列ストレージ | 整数コード + ルックアップテーブル |
| 欠損値 | None / np.nan | pd.NA | pd.NA |
| メモリ | 最大 | 中程度 | 最小(低カーディナリティの場合) |
| 文字列メソッド | .strアクセサ | .strアクセサ | .strアクセサ |
| 比較 | 一貫性がない場合あり | 一貫性あり | 一貫性あり |
| ソート | 辞書順 | 辞書順 | カスタム順序に対応 |
| 最適な用途 | レガシーコードとの互換性 | 新規プロジェクトに推奨 | 低カーディナリティのカラム |
▶ サンプル:3つの型のメモリ比較
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:3つの型のメモリ比較(難易度 ⭐⭐)
PYTHON
import pandas as pd
import numpy as np
# 1000行、ユニークな都市は5つ
cities = ['New York', 'London', 'Tokyo', 'Paris', 'Sydney']
data = [cities[i % 5] for i in range(1000)]
s_object = pd.Series(data, dtype='object')
s_string = pd.Series(data, dtype='string')
s_category = pd.Series(data, dtype='category')
print(f"object: {s_object.memory_usage(deep=True) / 1024:.1f} KB")
print(f"string: {s_string.memory_usage(deep=True) / 1024:.1f} KB")
print(f"category: {s_category.memory_usage(deep=True) / 1024:.1f} KB")
# object: ~62 KB
# string: ~55 KB
# category: ~5 KB ← 12倍小さい!
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
🔥 よくある落とし穴: ユニーク値の数が行数に近づく(高カーディナリティ)と、categoryはobjectよりも多くのメモリを使用します。完全なマッピングテーブルを維持する必要があるためです。経験則として、ユニーク値が行数の50%未満の場合にcategoryが効果を発揮します。
5. 型変換メソッド
(1) astype:明示的な変換
▶ サンプル:astype型変換
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:astype型変換(難易度 ⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'price_str': ['9.99', '19.99', '29.99'],
'quantity_int': [1, 3, 5],
'flag_str': ['True', 'False', 'True']
})
# 文字列からfloatへ変換
df['price'] = df['price_str'].astype(float)
# 整数から文字列へ変換(IDカラム用)
df['qty_str'] = df['quantity_int'].astype(str)
# 文字列からブール型へ変換(注意:文字列の'True'/'False' → bool)
df['flag'] = df['flag_str'].map({'True': True, 'False': False})
print(df.dtypes)
# price_str object
# quantity_int int64
# flag_str object
# price float64
# qty_str object
# flag bool
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) convert_dtypes:最適な型の自動推論
▶ サンプル:convert_dtypes自動変換
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:convert_dtypes自動変換(難易度 ⭐⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'name': ['アリス', 'ボブ', 'チャーリー'],
'age': [28, 34, 25],
'score': [85.5, 92.0, 78.3],
'active': [True, True, False]
})
# 最適なNullable dtypeに変換
df_converted = df.convert_dtypes()
print(df_converted.dtypes)
# name string ← object → StringDtype
# age Int64 ← int64 → nullable Int64
# score Float64 ← float64 → nullable Float64
# active boolean ← bool → nullable boolean
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(3) infer_objects:objectカラムの最適な型を推論
▶ サンプル:infer_objects推論
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:infer_objects推論(難易度 ⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'a': [1, 2, 3], # objectとして保存されている
'b': ['x', 'y', 'z'] # objectのまま
}, dtype='object')
print(df.dtypes)
# a object
# b object
df_inferred = df.infer_objects()
print(df_inferred.dtypes)
# a int64 ← 内容から推論された
# b object ← まだobject(文字列はそのまま)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(4) 変換メソッドの比較
| メソッド | 目的 | 自動/手動 | Nullable |
|---|---|---|---|
| astype() | 指定した型に強制変換 | 手動 | 自動ではない |
| convert_dtypes() | 最適なNullable型を推論 | 自動 | はい |
| infer_objects() | objectカラムの型を推論 | 自動 | 自動ではない |
6. Nullable型:整数の欠損値問題を解決する
(1) Nullable型が必要な理由
NumPyのint64はNaNを保存できません。整数カラムに欠損値がある場合、Pandasはカラム全体をfloat64にアップキャストせざるを得ず、元の型が失われてしまいます。
▶ サンプル:Nullable型と従来型の比較
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:Nullable型と従来型の比較(難易度 ⭐⭐)
PYTHON
import pandas as pd
import numpy as np
# 従来型:NaNを含むintカラム → floatに強制変換される
s_trad = pd.Series([1, 2, np.nan, 4])
print(s_trad) # 1.0, 2.0, NaN, 4.0 — floatになってしまう!
print(s_trad.dtype) # float64
# Nullable型:Int64は整数型を維持し、<NA>で欠損を表現
s_null = pd.Series([1, 2, pd.NA, 4], dtype='Int64')
print(s_null) # 1, 2, <NA>, 4 — 整数のまま!
print(s_null.dtype) # Int64
# Nullableブール型
b_null = pd.Series([True, False, pd.NA], dtype='boolean')
print(b_null)
# Nullable文字列型
str_null = pd.Series(['アリス', pd.NA, 'チャーリー'], dtype='string')
print(str_null)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) Nullable型一覧
| Nullable型 | 従来の対応型 | 欠損値マーカー | 適用場面 |
|---|---|---|---|
| Int8/16/32/64 | int8/16/32/64 | pd.NA | 欠損値を含む整数カラム |
| Float32/64 | float32/64 | pd.NA | 欠損値を含む浮動小数点カラム |
| boolean | bool | pd.NA | 欠損値を含むブールカラム |
| string | object | pd.NA | 文字列カラム(objectの代替) |
💡 ヒント: Nullable型は
pd.NAを使用して欠損値を統一的に表現し、np.nan / None / NaTが混在する煩雑な状況を解消します。演算時には、pd.NAは「伝播ルール」に従います。つまり、pd.NAを含む演算はすべてpd.NAを返します。
7. メモリ最適化の実践
(1) メモリ使用量の確認
▶ サンプル:memory_usage分析
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:memory_usage分析(難易度 ⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'id': range(10000),
'city': ['New York', 'London', 'Tokyo', 'Paris', 'Sydney'] * 2000,
'score': [85.5 + i * 0.1 for i in range(10000)],
'status': ['Active', 'Inactive', 'Pending'] * 3333 + ['Active']
})
# カラムごとのメモリ使用量(objectカラムにはdeep=Trueが必要)
print(df.memory_usage(deep=True))
# Index 80
# id 80000 ← 1万行のint64
# city 630000 ← object(非常に大きい!)
# score 80000 ← float64
# status 460000 ← object(非常に大きい!)
# 合計
total = df.memory_usage(deep=True).sum() / 1024 / 1024
print(f"合計: {total:.1f} MB")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) 最適化戦略
▶ サンプル:エンドツーエンドのメモリ最適化
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:エンドツーエンドのメモリ最適化(難易度 ⭐⭐⭐)
PYTHON
import pandas as pd
df = pd.DataFrame({
'id': range(10000),
'city': ['New York', 'London', 'Tokyo', 'Paris', 'Sydney'] * 2000,
'score': [85.5 + i * 0.1 for i in range(10000)],
'status': ['Active', 'Inactive', 'Pending'] * 3333 + ['Active']
})
mem_before = df.memory_usage(deep=True).sum() / 1024 / 1024
# 1. 低カーディナリティの文字列カラム → category
df['city'] = df['city'].astype('category')
df['status'] = df['status'].astype('category')
# 2. 数値のダウンキャスト
df['id'] = pd.to_numeric(df['id'], downcast='integer') # int64 → int16
df['score'] = pd.to_numeric(df['score'], downcast='float') # float64 → float32
mem_after = df.memory_usage(deep=True).sum() / 1024 / 1024
print(f"最適化前: {mem_before:.1f} MB")
print(f"最適化後: {mem_after:.1f} MB")
print(f"削減率: {(1 - mem_after/mem_before)*100:.0f}%")
print(f"\n最適化後のdtype:")
print(df.dtypes)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(3) ダウンキャスト対応表
| 元の型 | downcast='integer' | downcast='float' | 削減率 |
|---|---|---|---|
| int64 | int8/int16/int32(最小の型を自動選択) | — | 50%〜75% |
| float64 | — | float32 | 50% |
| uint64 | uint8/uint16/uint32 | — | 50%〜75% |
8. 完全な例:大規模顧客テーブルの最適化
▶ サンプル:顧客テーブルの完全な最適化パイプライン
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:顧客テーブルの完全な最適化パイプライン(難易度 ⭐⭐⭐)
PYTHON
import pandas as pd
import numpy as np
# ============================================
# 総合例:顧客テーブルの
# 完全な最適化パイプライン
# ============================================
# 1. 現実的な顧客データの作成
n = 50000
df = pd.DataFrame({
'customer_id': range(n),
'name': [f'Customer_{i:05d}' for i in range(n)],
'city': np.random.choice(['New York', 'London', 'Tokyo', 'Paris',
'Sydney', 'Berlin', 'Toronto', 'Seoul'], n),
'age': np.random.randint(18, 80, n),
'membership': np.random.choice(['Basic', 'Silver', 'Gold', 'Platinum'], n),
'points': np.random.randint(0, 100000, n),
'satisfaction': np.random.choice([1, 2, 3, 4, 5, np.nan], n, p=[0.05,0.1,0.2,0.3,0.3,0.05])
})
# 2. 最適化前の分析
print("=== 最適化前 ===")
print(df.dtypes)
mem_before = df.memory_usage(deep=True).sum() / 1024 / 1024
print(f"合計メモリ: {mem_before:.1f} MB")
# 3. 最適化
# 低カーディナリティの文字列 → category
for col in ['city', 'membership']:
df[col] = df[col].astype('category')
# 整数のダウンキャスト
for col in ['customer_id', 'age', 'points']:
df[col] = pd.to_numeric(df[col], downcast='integer')
# NaNを含むfloat → nullable Int8
df['satisfaction'] = df['satisfaction'].astype('Int8')
# 4. 最適化後の分析
print("\n=== 最適化後 ===")
print(df.dtypes)
mem_after = df.memory_usage(deep=True).sum() / 1024 / 1024
print(f"合計メモリ: {mem_after:.1f} MB")
print(f"削減率: {(1 - mem_after/mem_before)*100:.0f}%")
# 5. データの整合性検証
print(f"\n=== 整合性チェック ===")
print(f"行数: {len(df)}")
print(f"satisfactionのNaN数: {df['satisfaction'].isna().sum()}")
print(f"ユニークな都市数: {df['city'].nunique()}")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
❓ よくある質問
Q objectとstringの違いは何ですか?
A objectはPythonオブジェクトのポインタの配列です。各要素が独立したPython文字列オブジェクトであり、メモリオーバーヘッドが大きくなります。string(StringDtype)はPandas 1.0以降で導入された専用の文字列型で、欠損値にpd.NAを使用し、より一貫した演算セマンティクスを提供します。新規プロジェクトでは、objectよりもstringを優先してください。
Q Nullable型のメリットは何ですか?
A 「欠損値を含む整数カラムがfloatに強制変換される」という長年の問題を解決します。Int64は整数とpd.NAの両方を保持でき、整数のセマンティクスを維持します。例えば、欠損値を含む顧客の年齢カラムは、float64になるのではなく整数型(Int8)のまま保持されます。
Q categoryはいつ使うべきですか?
A カラムのユニーク値が行数よりもはるかに少ない場合です(経験則:ユニーク値が行数の50%未満)。典型的な例は、city、gender、status、tierなどの有限カテゴリのカラムです。categoryは繰り返される文字列を整数コードとルックアップテーブルに置き換え、メモリを90%以上削減します。高カーディナリティのカラム(ユーザーIDなど)には適していません。
Q convert_dtypesとastypeの違いは何ですか?
A astypeはターゲットの型を手動で指定する必要があります(例:
astype('int64'))。一方、convert_dtypesは最適なNullable型を自動的に推論します(object→string、int64→Int64、float64→Float64)。astypeはより精密で、convert_dtypesはより便利です。Q メモリ使用量を確認するにはどうすればよいですか?
A
df.memory_usage(deep=True)は各カラムのバイト数を返します。deep=Trueを指定すると、objectカラムの実際の文字列メモリが計算されます(ポインタサイズだけでなく)。df.info(memory_usage='deep')でも合計メモリを確認できます。Q downcastは安全ですか?
A はい。Pandasの
pd.to_numeric(downcast=...)は、データ範囲を保持できる最小の型を自動的に選択します。例えば、0〜100の整数はuint8(0〜255)が選択され、オーバーフローは発生しません。ただし、後でその範囲外のデータを追加すると、暗黙的に切り捨てられたりアップキャストされたりする可能性があります。データクリーニングが完了した後の最終ステップとしてdowncastを実行することをお勧めします。Q なぜ文字列カラムのmemory_usageがこんなに大きいのですか?
A object/stringカラムの各要素は独立したPythonオブジェクトであり、50バイト以上のオブジェクトヘッダーオーバーヘッドがあります。1万行の文字列は600 KBを消費するのに対し、同じ行数のint64はわずか80 KBです。解決策:低カーディナリティのデータにはcategoryを使用し、高カーディナリティのデータにはチャンク処理を検討してください。
📖 まとめ
- PandasのdtypeシステムはNumPyよりも豊富で、Nullable型、category、StringDtypeが追加されています
- objectはメモリを大量に消費します。低カーディナリティの文字列カラムはcategoryに変換すべきです(90%以上のメモリ削減)
- Nullable型(Int64/Float64/boolean/string)はpd.NAで欠損値を統一し、「整数カラムにNaNを保持できない」問題を解決します
- astypeは手動で型を変換し、convert_dtypesはNullable型を自動推論し、infer_objectsはobjectカラムの型を推論します
- メモリ最適化の3ステップ:低カーディナリティの文字列→category → 数値のダウンキャスト → float64→float32
- memory_usage(deep=True)で実際のメモリ使用量を確認してください。objectカラムの実際のメモリはポインタサイズをはるかに超えます
- データクリーニング完了後にdowncastを実行し、後から追加するデータが型の範囲を超えないようにしてください
📝 練習問題
- 基礎(難易度 ⭐):3つのカラム(文字列/整数/浮動小数点)を持つDataFrameを作成してください。dtypesで型を確認し、astypeを使って整数カラムをint8に、浮動小数点カラムをfloat32に変換してください。memory_usageの変化を比較してください。
- 中級(難易度 ⭐⭐):NaNを含む整数Seriesを作成してください。従来の方法(自動的にfloat64に変換される)とNullable Int64型の両方で処理し、dtypeと演算の動作を比較してください。次に、ユニーク値が5つの文字列カラムをcategory型で最適化してください。
- チャレンジ(難易度 ⭐⭐⭐):4つのカラム(低カーディナリティ文字列 / 高カーディナリティ文字列 / 整数 / 浮動小数点)を持つ1万行のシミュレーションDataFrameを作成してください。完全なメモリ最適化パイプラインを実行してください:確認 → 低カーディナリティ → category → ダウンキャスト → Nullable → 検証。各ステップのメモリ変化と最終的な削減率を出力してください。



