迭代 df 列列表并有效地用字典中的值替换现有键 python
Iterating over df column list and replacing existing keys with their values from a dictionary efficiently python
我有一个关于物品概率的字典。
我有一个 500 万行的 df,看起来像这样:
user_id item_list
U1 [I1,I3,I4]
U2 [I5,I4]
和一个字典:{'I1': 0.1, 'I4': 0.4, ..}
我正在尝试遍历每一行并创建一个包含概率的列表,如下所示:
user_id item_list prob_list
U1 [I1,I3,I4] [0.1,0.4]
U2 [I5,I4] [0.4]
- 并非所有项目都有概率。
这是我的代码:
keys = list(prob_dict.keys())
df['prob_list'] = df.progress_apply(lambda x: get_probability(prob_dict=prob_dict,
keys=keys, item_list=x['item_list']),axis=1)
def get_probability(prob_dict, keys, item_list):
prob_list = []
for item in item_list:
if item in keys:
prob = prob_dict[item ]
prob_list.append(prob)
if len(prob_list)>=1:
return prob_list
else:
return np.nan
因为我使用的是 tqdm,所以我知道它需要多长时间(120 小时),这太多了,而且显然效率不高。
关于如何更有效地做到这一点有什么想法吗?
使用 Series.transform
to transform each item in item_list
to pandas Series and correspondingly map this series using Series.map
到映射字典 d
,然后使用 dropna
删除 NaN
值:
d = {'I1': 0.1, 'I4': 0.4}
df['prob_list'] = (
df['item_list'].transform(lambda s: pd.Series(s).map(d).dropna().values)
)
更新(使用multiprocessing
提高映射item_list
到prob_list
的速度):
import multiprocessing as mp
def map_prob(s):
s = s[~s.isna()]
return s.transform(
lambda lst: [d[k] for k in lst if k in d] or np.nan)
def parallel_map(item_list):
splits = np.array_split(item_list, mp.cpu_count())
pool = mp.Pool()
prob_list = pd.concat(pool.map(map_prob, splits))
pool.close()
pool.join()
return prob_list
df['prob_list'] = parallel_map(df['item_list'])
结果:
# print(df)
uer_id item_list prob_list
0 U1 [I1, I3, I4] [0.1, 0.4]
1 U2 [I5, I4] [0.4]
我有一个关于物品概率的字典。 我有一个 500 万行的 df,看起来像这样:
user_id item_list
U1 [I1,I3,I4]
U2 [I5,I4]
和一个字典:{'I1': 0.1, 'I4': 0.4, ..}
我正在尝试遍历每一行并创建一个包含概率的列表,如下所示:
user_id item_list prob_list
U1 [I1,I3,I4] [0.1,0.4]
U2 [I5,I4] [0.4]
- 并非所有项目都有概率。
这是我的代码:
keys = list(prob_dict.keys())
df['prob_list'] = df.progress_apply(lambda x: get_probability(prob_dict=prob_dict,
keys=keys, item_list=x['item_list']),axis=1)
def get_probability(prob_dict, keys, item_list):
prob_list = []
for item in item_list:
if item in keys:
prob = prob_dict[item ]
prob_list.append(prob)
if len(prob_list)>=1:
return prob_list
else:
return np.nan
因为我使用的是 tqdm,所以我知道它需要多长时间(120 小时),这太多了,而且显然效率不高。
关于如何更有效地做到这一点有什么想法吗?
使用 Series.transform
to transform each item in item_list
to pandas Series and correspondingly map this series using Series.map
到映射字典 d
,然后使用 dropna
删除 NaN
值:
d = {'I1': 0.1, 'I4': 0.4}
df['prob_list'] = (
df['item_list'].transform(lambda s: pd.Series(s).map(d).dropna().values)
)
更新(使用multiprocessing
提高映射item_list
到prob_list
的速度):
import multiprocessing as mp
def map_prob(s):
s = s[~s.isna()]
return s.transform(
lambda lst: [d[k] for k in lst if k in d] or np.nan)
def parallel_map(item_list):
splits = np.array_split(item_list, mp.cpu_count())
pool = mp.Pool()
prob_list = pd.concat(pool.map(map_prob, splits))
pool.close()
pool.join()
return prob_list
df['prob_list'] = parallel_map(df['item_list'])
结果:
# print(df)
uer_id item_list prob_list
0 U1 [I1, I3, I4] [0.1, 0.4]
1 U2 [I5, I4] [0.4]