首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用不同的行值同时过滤Pandas

用不同的行值同时过滤Pandas
EN

Stack Overflow用户
提问于 2018-06-27 11:30:53
回答 3查看 77关注 0票数 0

我有一个包含product_id和它们的property _id的巨大数据,请注意,对于每个属性,都以新索引开头。我需要为每个property_id同时通过不同的product_id值进行过滤。有办法快点吗?

代码语言:javascript
复制
out_df

product_id  property_id
0   3588    1
1   3588    2
2   3588    5
3   3589    1
4   3589    3
5   3589    5
6   3590    1
7   3590    2
8   3590    5

例如,希望通过两个属性对每个product_id进行过滤,这些属性在不同的行(如out_df.loc[(out_df['property_id'] == 1) & (out_df['property_id'] == 2)] )分配,而不是)。我需要这样的东西,但是对每个product_id列的所有行都同时工作。

我知道这可以通过groupby变成列表

代码语言:javascript
复制
3587    [2, 1, 5]
3588    [1, 3, 5]
3590    [1, 2, 5]

并在列表中找到交叉口。

代码语言:javascript
复制
gp_df.apply(lambda r: {1, 2} < (set(r['property_id'])), axis=1)  

但这需要时间,同时Pandas的通用过滤也大大优化了速度(请相信在搜索引擎ElasticSearch、狮身人面像等中使用一些复杂的正、逆索引)。

预期输出:其中{1和2}都有。

代码语言:javascript
复制
3587    [2, 1, 5]
3590    [1, 2, 5]
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-27 12:28:09

由于这既是一个功能问题,也是一个性能问题,所以我将使用这样的交叉方法:

代码语言:javascript
复制
df = pd.DataFrame({'product_id': [3588, 3588, 3588, 3589, 3589, 3589, 3590, 3590,3590], 
                   'property_id': [1, 2, 5, 1, 3, 5, 1, 2, 5]})

df = df.set_index(['property_id'])

print("The full DataFrame:")
print(df)

start = time()

for i in range(1000):
    s1 = df.loc[(1), 'product_id']
    s2 = df.loc[(2), 'product_id']

    s_done = pd.Series(list(set(s1).intersection(set(s2))))

print("Overlapping product_id's")
print(time()-start)

迭代查找1000次需要0.93秒在我的ThinkPad T450s上。我冒昧地测试了@jezrael的两个建议,它们是在2.11和2.00秒时提出的,groupby的方法是,软件工程方面的建议更优雅。

根据数据集的大小和性能的重要性,您还可以切换到更简单的数据类型,如经典字典,并获得进一步的速度。

木星笔记本可以在这里找到:intersection.ipynb

票数 1
EN

Stack Overflow用户

发布于 2018-06-27 11:46:41

你是说像这样的事吗?

代码语言:javascript
复制
result = out_df.loc[out_df['property_id'].isin([1,2]), :]

如果你想要的话,你可以根据product_id放一个副本.

票数 1
EN

Stack Overflow用户

发布于 2018-06-27 11:48:27

最简单的方法是在比较集中使用GroupBy.transform

代码语言:javascript
复制
s = {1, 2}
a = df[df.groupby('product_id')['property_id'].transform(lambda r: s < set(r))]
print (a)
   product_id  property_id
0        3588            1
1        3588            2
2        3588            5
6        3590            1
7        3590            2
8        3590            5

另一种解决方案是只筛选集合的值,首先删除重复的值:

代码语言:javascript
复制
df1 = df[df['property_id'].isin(s) & ~df.duplicated(['product_id', 'property_id'])]

然后,有必要检查每个组的长度是否与这个解决方案的集合长度相同。

代码语言:javascript
复制
f, u = df1['product_id'].factorize()
ids = df1.loc[np.bincount(f)[f] == len(s), 'product_id'].unique()

最后,使用product_id按条件过滤所有行:

代码语言:javascript
复制
a = df[df['product_id'].isin(ids)]
print (a)
   product_id  property_id
0        3588            1
1        3588            2
2        3588            5
6        3590            1
7        3590            2
8        3590            5
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51061711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档