首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对包含自定义分组的pandas计算进行矢量化?

如何对包含自定义分组的pandas计算进行矢量化?
EN

Stack Overflow用户
提问于 2017-05-08 18:47:13
回答 1查看 156关注 0票数 2

我有一个很大的数据框架,它将用户(索引)映射到项目(列)的计数:

代码语言:javascript
复制
users_items = pd.DataFrame(np.array([[0, 1, 1, 0],      # user 0
                                     [1, 0, 0, 0],      # user 1
                                     [5, 0, 0, 9],      # user 2
                                     [0, 3, 5, 0],      # user 3
                                     [0, 2, 2, 0],      # user 4
                                     [7, 0, 0, 1],      # user 5
                                     [3, 5, 0, 4]]),    # user 6
                           columns=list('ABCD'))

对于每个用户,我希望找到至少具有相同项目的非零计数的所有用户,并对其计数求和。因此,对于用户1,这将是用户1、2、5和6,并且计数的和等于[16, 5, 0, 14]。这可以用来根据“相似”用户获得的项目向用户推荐新项目。

这个简单的实现使用一个签名作为正则表达式来过滤出相关的行,并使用一个for循环遍历所有签名:

代码语言:javascript
复制
def create_signature(request_counts):
    return ''.join('x' if count else '.' for count in request_counts)

users_items['signature'] = users_items.apply(create_signature, axis=1).astype('category')

current_items = users_items.groupby('signature').sum()

similar_items = pd.DataFrame(index=current_items.index,
                             columns=current_items.columns)

for signature in current_items.index:
    row = current_items.filter(regex=signature, axis='index').sum()
    similar_items.loc[signature] = row

结果是:

代码语言:javascript
复制
            A  B  C   D
signature              
.xx.        0  6  8   0
x...       16  5  0  14
x..x       15  5  0  14
xx.x        3  5  0   4

这可以很好地工作,但对于包含100k用户和大约600个项目的实际数据集来说,它太慢了。生成签名只需要10秒,但循环所有(40k)签名需要几个小时。

向量化循环应该会提供一个巨大的性能提升,但我使用Pandas的经验有限,所以我不确定如何去做。甚至有可能将这种类型的计算向量化?也许是用口罩?

EN

回答 1

Stack Overflow用户

发布于 2017-05-08 22:56:31

您可以使用frozenset而不是string作为签名

代码语言:javascript
复制
def create_signature(request_counts):
    return frozenset(request_counts[request_counts != 0].index)

另一种选择是

代码语言:javascript
复制
def create_signature(request_counts):
    return frozenset(request_counts.replace({0: None}).dropna().index)

我没有足够大的数据集来查看其中一个是否比另一个更快。

如果有重复的列,请在.index之前插入对reset_index()的调用

这使您可以在最后对过滤器进行矢量化

代码语言:javascript
复制
for signature in current_items.index:
    row = current_items[signature <= current_items.index].sum()
    similar_items.loc[signature] = row

结果:

代码语言:javascript
复制
signature                   A   B   C   D
frozenset({'B', 'C'})       0   6   8   0
frozenset({'A'})            16  5   0   14
frozenset({'A', 'D'})       15  5   0   14
frozenset({'B', 'A', 'D'})  3   5   0   4
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43845672

复制
相关文章

相似问题

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