python - 在数据帧切片上并行化 Pandas 的正确方法
问题描述
假设我有一个包含 N 个多值分类列的数据框,并且我想使用 Pandas 尽可能快地对它们进行编码。
这是我到目前为止所取得的成就,但不确定它是否是并行化 Pandas 的最佳方法(我希望尽可能使用矢量化方法):
def encode_single_categorical(input_series):
encoded_categorical_feature_data_frame = input_series.str.join(
'|').str.get_dummies().astype(
pd.np.bool).add_prefix(
input_series.name + '_')
return encoded_categorical_feature_data_frame
def encode_multi_valued_categorical_features(input_data_frame, categorical_features):
with Pool(cpu_count()) as p:
encoded_categorical_data_frames = p.map(encode_single_categorical,
[input_data_frame[categorical_feature] for
categorical_feature in categorical_features])
return pd.concat(encoded_categorical_data_frames, axis=1)
我另外添加了一个测试,但这里的重点是方法。该解决方案在功能上有效,更多的是关于“它是 Pandas 的最佳实践吗?
def test_encode_multi_valued_categorical_features(self):
categorical_features = ['productCategories', 'productTypes']
input_data_frame = pd.DataFrame({'querySource': ['source1', pd.np.nan, 'source3'],
'productTypes': [["t1", "t2", "t3"], ["t6", "t4", "t3"], ["t6", "t1"]],
'productBrand': ['brand1', 'brand2', 'brand3'],
'productCategories': [["c1", "c2", "c3"], ["c6", "c4", "c3"], ["c6", "c1"]],
})
expected_data_frame = pd.DataFrame({'querySource': ['source1', pd.np.nan, 'source3'],
'productBrand': ['brand1', 'brand2', 'brand3'],
'productCategories_c1': [True, False, True],
'productCategories_c2': [True, False, False],
'productCategories_c3': [True, True, False],
'productCategories_c4': [False, True, False],
'productCategories_c6': [False, True, True],
'productTypes_t1': [True, False, True],
'productTypes_t2': [True, False, False],
'productTypes_t3': [True, True, False],
'productTypes_t4': [False, True, False],
'productTypes_t6': [False, True, True],
})
result = utils.encode_multi_valued_categorical_features3(input_data_frame, categorical_features)
pd.testing.assert_frame_equal(result, expected_data_frame)
解决方案
我建议你使用 Pandas 中内置的矢量化方法来完成,它读起来更清晰,应该更快。
下面是一列的示例,您应该能够将其转换为函数并遍历所有相关列。
# get super list of all lists in column 'productCategories'
list_all_cat = input_data_frame['productCategories'].sum()
print(list_all_cat)
> ['c1', 'c2', 'c3', 'c6', 'c4', 'c3', 'c6', 'c1']
# get unique list of productCategories
list_all_cat_unique = list(set(list_all_cat))
print(list_all_cat_unique)
> ['c4', 'c6', 'c2', 'c3', 'c1']
# loop over this unique list
for cat in list_all_cat_unique:
# new column defaulting to False
input_data_frame['productCategories_' + cat] = False
# encode
input_data_frame.loc[input_data_frame['productCategories'].apply(lambda x: cat in x) , 'productCategories_' + cat] = True
print(input_data_frame['productCategories_c4'])
> 0 False
1 True
2 False
Name: productCategories_c4, dtype: bool
推荐阅读
- django - 使用 .html 扩展名 Django 下载媒体文件
- java - org.hsqldb.HsqlException: 升级spring boot版本时用户缺少权限或找不到对象
- oop - 设计模式 - 解析 4 个不同的 JSON 文件
- python - 如何在给定的前提条件下仅删除某些字符
- flutter - 为什么导航栈隐藏在 Flutter 中?
- google-cloud-platform - Google Cloud Vision API 在太平洋标准时间下午 1 点之前无法访问图片网址
- php - 如何使用 x509 证书在 PHP 中签署 XML?
- php - 如何根据结果计数将 div 拆分为两列或三列?
- python - GitHub 工作流/自动化的 PyTest 和受控测试失败
- discord.py - 等待时间,然后 DM 与机器人,一次与多个用户