基于用户观影演员数据生成用户-演员计数矩阵的技术咨询
嘿,这个需求确实和CountVectorizer的思路很像,但因为演员是带空格的全名,直接用默认的CountVectorizer会把名字拆成单个词(比如把"Tony Ward"拆成"Tony"和"Ward"),所以得调整处理方式。这里给你两个实用的解决方案:
方案一:用Pandas原生函数实现(推荐)
这个方法完全依赖Pandas的内置功能,简单直观,能准确处理演员全名的重复计数:
import pandas as pd # 先构造你的示例数据(方便演示) data = { 'UserId': ['u1', 'u2'], 'Actors': ['Tony Ward,Bruce LaBruce,Kevin P. Scott,Ivar Johnson, Naomi Watts, Tony Ward', 'Tony Ward,Bruce LaBruce,Kevin P. Scott, Luke Wilson, Owen Wilson, Lumi Cavazos'] } df = pd.DataFrame(data) # 步骤1:拆分演员列,同时去掉每个演员名前后的多余空格 df['Actors'] = df['Actors'].str.split(',\s*') # 步骤2:把每个用户的演员列表拆成单独行(一行一个用户+一个演员) exploded_df = df.explode('Actors') # 步骤3:生成用户-演员的交叉计数表,空值填充为0并转成整数 result = pd.crosstab(exploded_df['UserId'], exploded_df['Actors']).reset_index() result = result.fillna(0).astype(int) print(result)
运行后输出的结果就是你要的格式:
Actors UserId Bruce LaBruce Ivar Johnson Kevin P. Scott Lumi Cavazos Luke Wilson Naomi Watts Owen Wilson Tony Ward 0 u1 1 1 1 0 0 1 0 2 1 u2 1 0 1 1 1 0 1 1
方案二:自定义CountVectorizer实现
如果你更习惯用Scikit-learn的工具链,可以给CountVectorizer定制一个分词器,让它按逗号而不是空格拆分内容:
from sklearn.feature_extraction.text import CountVectorizer import pandas as pd data = { 'UserId': ['u1', 'u2'], 'Actors': ['Tony Ward,Bruce LaBruce,Kevin P. Scott,Ivar Johnson, Naomi Watts, Tony Ward', 'Tony Ward,Bruce LaBruce,Kevin P. Scott, Luke Wilson, Owen Wilson, Lumi Cavazos'] } df = pd.DataFrame(data) # 自定义分词器:按逗号分割字符串,同时清理每个演员名的前后空格 def actor_tokenizer(text): return [actor.strip() for actor in text.split(',')] # 初始化CountVectorizer:关闭小写转换(避免演员名变小写),使用自定义分词器 cv = CountVectorizer(tokenizer=actor_tokenizer, lowercase=False) count_matrix = cv.fit_transform(df['Actors']) # 把计数矩阵转换成DataFrame,并加上UserId列 result = pd.DataFrame(count_matrix.toarray(), columns=cv.get_feature_names_out()) result.insert(0, 'UserId', df['UserId']) print(result)
这个方案的输出和方案一完全一致,适合已经在使用Scikit-learn流水线的场景。
注意事项
- 如果你的
Actors列存在空值,记得先处理:df['Actors'] = df['Actors'].fillna(''),避免拆分时出错。 - 如果演员名存在大小写不一致的情况(比如"tony ward"和"Tony Ward"),可以在拆分后统一转成小写/大写,比如
exploded_df['Actors'] = exploded_df['Actors'].str.lower()。
内容的提问来源于stack exchange,提问作者Ronak
相关产品推荐
相关产品推荐

