给定值列表的大熊猫在列中查找具有此值的行

时间:2019-04-06 12:51:57

标签: python pandas

我有商品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']),想知道是否有明显更好的选择吗?

2 个答案:

答案 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行中的query10M函数:

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