如何优化含多标签的电影Genre特征预处理?(Python)
机器学习特征预处理:多类别Genre列优化方案
问题背景
我在做机器学习任务的特征预处理,遇到Genre特征列的问题:该列的每个值是逗号分隔的多个类别字符串(已按字母排序)。原本想用.startswith()提取首个类别,但这个思路不可行。我是Python新手,写了下面的代码,但数据库里多数电影都是多类别,导致大量样本被归为Other,急需更优的解决方案。
现有代码
cols_to_check = ['Action','Drama','Comedy', 'Romance', 'History', 'War'] def update_genre(row): x = row['genre'] if x == 'Action': row["Genre"] = 'Action' elif x == 'Comedy': row["Genre"] = 'Comedy' elif x == 'Drama': row["Genre"] = 'Drama' elif x == 'Romance': row["Genre"] = 'Romance' elif x == 'War': row["Genre"] = 'War' else: row["Genre"] = 'Other' return row df[["Genre"]] = 0 df= df.apply(update_genre, axis=1)
数据样例
Drama 8498 Comedy 5420 Comedy, Drama 2654 Drama, Romance 2529 Comedy, Romance 1777 ... War, Action, Adventure 1 Romance, Thriller, Western 1 Action, Thriller, Western 1 Horror, Comedy, Music 1 Comedy, Sci-Fi, Sport 1
期望目标
能正确提取特征中的类别(无论是单一类别还是子字符串形式的多类别),避免大量样本被归为Other。
解决方案
根据任务需求,提供三种常用处理思路,可根据机器学习任务类型(分类/回归)选择:
方案1:提取所有匹配的目标类别(多标签处理)
如果任务支持多标签分类,或想保留所有相关类别信息,可将每个目标类别拆为单独列,标记样本是否包含该类别:
import pandas as pd cols_to_check = ['Action','Drama','Comedy', 'Romance', 'History', 'War'] # 为每个目标类别创建新列,判断样本是否包含该类别 for genre in cols_to_check: df[f'Genre_{genre}'] = df['genre'].str.contains(genre).astype(int)
示例:若genre值为Comedy, Drama,则Genre_Comedy=1、Genre_Drama=1,其余目标类别列值为0。
方案2:优先匹配高频目标类别(单标签处理)
若任务仅需单标签,可按目标类别的数据出现频率设置优先级,提取第一个匹配的类别:
# 按数据中类别出现频率排序,调整顺序可改变优先级 cols_to_check = ['Drama','Comedy','Action', 'Romance', 'War', 'History'] def extract_main_genre(row): genre_str = row['genre'] for genre in cols_to_check: if genre in genre_str: return genre return 'Other' df['Genre'] = df.apply(extract_main_genre, axis=1)
示例:Comedy, Drama会被归为Drama(因优先级更高),若想优先取字符串中第一个出现的类别,调整cols_to_check顺序即可。
方案3:多标签独热编码(适配传统机器学习模型)
若需将类别转为模型可直接使用的数值特征,可结合MultiLabelBinarizer实现多标签独热编码:
from sklearn.preprocessing import MultiLabelBinarizer import pandas as pd cols_to_check = ['Action','Drama','Comedy', 'Romance', 'History', 'War'] # 将genre字符串拆分为仅包含目标类别的列表 df['genre_list'] = df['genre'].str.split(', ').apply(lambda x: [g for g in x if g in cols_to_check]) # 执行多标签独热编码 mlb = MultiLabelBinarizer(classes=cols_to_check) genre_onehot = mlb.fit_transform(df['genre_list']) # 转换为DataFrame并合并到原数据 genre_onehot_df = pd.DataFrame(genre_onehot, columns=mlb.classes_) df = pd.concat([df, genre_onehot_df], axis=1)
内容的提问来源于stack exchange,提问作者Maria Li
相关产品推荐
相关产品推荐

