Pandas 類別資料
Categorical 是 Pandas 的一種特殊資料型別,用於處理只有有限幾種值的欄位(如性別、等級、城市等)。使用 Categorical 可以節省記憶體並提升效能。
建立 Categorical
從 Series 轉換
import pandas as pd
s = pd.Series(['low', 'high', 'medium', 'low', 'high'])
# 轉換成 category 型別
s_cat = s.astype('category')
print(s_cat)
0 low
1 high
2 medium
3 low
4 high
dtype: category
Categories (3, object): ['high', 'low', 'medium']
使用 Categorical 類別
# 基本建立
cat = pd.Categorical(['a', 'b', 'a', 'c'])
# 指定類別
cat = pd.Categorical(['a', 'b', 'a'], categories=['a', 'b', 'c'])
# 有順序的類別
cat = pd.Categorical(
['low', 'high', 'medium'],
categories=['low', 'medium', 'high'],
ordered=True
)
在 DataFrame 中使用
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'grade': pd.Categorical(['A', 'B', 'A'], categories=['A', 'B', 'C', 'D'])
})
print(df.dtypes)
name object
grade category
dtype: object
Categorical 的優點
節省記憶體
s_str = pd.Series(['apple'] * 10000)
s_cat = s_str.astype('category')
print(f"字串: {s_str.memory_usage(deep=True)} bytes")
print(f"類別: {s_cat.memory_usage(deep=True)} bytes")
當有大量重複值時,Categorical 的記憶體使用量會小很多。
提升效能
分組和排序等操作在 Categorical 上通常更快。
有序類別
# 建立有順序的類別
size = pd.Categorical(
['M', 'S', 'L', 'M', 'S'],
categories=['S', 'M', 'L'],
ordered=True
)
s = pd.Series(size)
# 可以進行比較
print(s > 'S')
0 True
1 False
2 True
3 True
4 False
dtype: bool
排序
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'size': pd.Categorical(['M', 'S', 'L'], categories=['S', 'M', 'L'], ordered=True)
})
# 按照定義的順序排序
df_sorted = df.sort_values('size')
print(df_sorted)
name size
1 Bob S
0 Alice M
2 Charlie L
類別操作
查看類別
s = pd.Series(['a', 'b', 'a', 'c']).astype('category')
# 查看所有類別
print(s.cat.categories)
# Index(['a', 'b', 'c'], dtype='object')
# 查看類別編碼
print(s.cat.codes)
# 0 0
# 1 1
# 2 0
# 3 2
# dtype: int8
新增類別
s = pd.Series(['a', 'b']).astype('category')
# 新增類別(不會新增資料)
s = s.cat.add_categories(['c', 'd'])
print(s.cat.categories)
# Index(['a', 'b', 'c', 'd'], dtype='object')
移除類別
# 移除指定類別
s = s.cat.remove_categories(['d'])
# 移除未使用的類別
s = s.cat.remove_unused_categories()
重新命名類別
s = pd.Series(['a', 'b', 'a']).astype('category')
# 重新命名
s = s.cat.rename_categories({'a': 'A', 'b': 'B'})
print(s)
0 A
1 B
2 A
dtype: category
Categories (2, object): ['A', 'B']
設定類別
# 設定新的類別(會把不在新類別中的值變成 NaN)
s = s.cat.set_categories(['A', 'C'])
print(s)
0 A
1 NaN
2 A
dtype: category
Categories (2, object): ['A', 'C']
重新排序類別
s = pd.Series(['low', 'high', 'medium']).astype('category')
# 設定順序
s = s.cat.reorder_categories(['low', 'medium', 'high'], ordered=True)
實際應用
等級資料
df = pd.DataFrame({
'student': ['Alice', 'Bob', 'Charlie', 'David'],
'grade': ['B', 'A', 'C', 'A']
})
# 轉換成有順序的類別
df['grade'] = pd.Categorical(
df['grade'],
categories=['F', 'D', 'C', 'B', 'A'],
ordered=True
)
# 找出 B 以上的學生
print(df[df['grade'] >= 'B'])
編碼轉換
df = pd.DataFrame({
'color': ['red', 'blue', 'red', 'green']
})
df['color'] = df['color'].astype('category')
# 取得數字編碼(用於機器學習)
df['color_code'] = df['color'].cat.codes
print(df)
color color_code
0 red 2
1 blue 0
2 red 2
3 green 1
統計分析
df = pd.DataFrame({
'age_group': pd.Categorical(
['young', 'adult', 'young', 'senior', 'adult'],
categories=['young', 'adult', 'senior'],
ordered=True
),
'value': [10, 20, 15, 30, 25]
})
# 分組統計(會按照類別順序)
print(df.groupby('age_group', observed=False)['value'].mean())
age_group
young 12.5
adult 22.5
senior 30.0
Name: value, dtype: float64
處理缺失類別
df = pd.DataFrame({
'month': pd.Categorical(['Jan', 'Mar'], categories=['Jan', 'Feb', 'Mar'])
})
# value_counts 會包含所有類別
print(df['month'].value_counts())
month
Jan 1
Mar 1
Feb 0
Name: count, dtype: int64