我有商品ID的列表 [1、2、3、4]
我想从另一个数据框中找到这些ID的行。 当有多种选择时,您选择哪一行都没有关系,我只想尽快。
user_id, item_id
1, 2
1, 3
1, 2
4, 4
5, 4
2, 3
3, 1
3, 2
输出(可能之一)
user_id, item_id
3, 1
3, 2
2, 3
4, 4
当前,我正在使用item_ids.to_frame().merge(df, on='item_id', how='inner').drop_duplicates(subset=['item_id'])
,想知道是否有明显更好的选择吗?
答案 0 :(得分:2)
首先通过Series.isin
进行过滤,然后通过DataFrame.drop_duplicates
除去重复项,最后根据需要进行排序:
L = [1, 2, 3, 4]
df = df[df['item_id'].isin(L)]
df = df.drop_duplicates('item_id', keep='last').sort_values('item_id')
print (df)
user_id item_id
6 3 1
7 3 2
5 2 3
4 5 4
性能-isin
行中的query
与10M
函数:
np.random.seed(2019)
item_ids = [1, 2, 3, 4]
N = 10 ** 7
#1% matched values
df = pd.DataFrame({'item_id':np.random.choice(item_ids + [5], p=(.025,.025,.025,.025,.9),size=N)})
In [296]: %timeit df.query('item_id in {}'.format(item_ids))
284 ms ± 12.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [297]: %timeit df[df['item_id'].isin(item_ids)]
174 ms ± 455 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
#50% matched values
df = pd.DataFrame({'item_id':np.random.choice(item_ids+ [5], p=(.125,.125,.125,.125,.5),size=N)})
In [299]: %timeit df.query('item_id in {}'.format(item_ids))
404 ms ± 5.69 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [300]: %timeit df[df['item_id'].isin(item_ids)]
299 ms ± 3.65 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#90% matched values
df = pd.DataFrame({'item_id':np.random.choice(item_ids+ [5], p=(.225,.225,.225,.225,.1),size=N)})
In [302]: %timeit df.query('item_id in {}'.format(item_ids))
480 ms ± 5.36 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [303]: %timeit df[df['item_id'].isin(item_ids)]
372 ms ± 2.87 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
答案 1 :(得分:1)
查询更快,因为它依赖于Numexpr包并支持快速向量化操作
df=pd.DataFrame({'user_id':[1,1,1,4,5,2,3,3],'item_id':[2,3,2,4,4,3,1,2]})
item_ids = [1, 2, 3, 4]
df.query('item_id in {}'.format(item_ids)).drop_duplicates('item_id', keep='first')
输出:
item_id user_id
0 2 1
1 3 1
3 4 4
6 1 3