繁体   English   中英

如何计算每组中最频繁的组合

[英]How to count most frequent combinations in each group

我有一个带有 post_ID 和 tag_ID 的长格式的 Pandas DataFrame(一个帖子到多个标签)。

+---------+--------+
| post_ID | tag_ID |
+---------+--------+
|       1 |      1 |
|       1 |      2 |
|       1 |      3 |
|       2 |      1 |
|       2 |      4 |
|       2 |      6 |
|       3 |      1 |
|       4 |      5 |
|       4 |      6 |
|     ... |    ... |
+---------+--------+

我的问题是:在查看按 post_ID 分组的标签时,最常见的两个标签组合是什么? 因此,我想要一个包含如下结果的框架:

+---------------------+-----+
| tag_ID_combinations |  n  |
+---------------------+-----+
|                 1,2 |  50 |
|                 3,4 | 200 |
|                 5,6 |  20 |
+---------------------+-----+

如果可能,post_ID 1 的标签 1,2 和 3 应该算作 1,2 、 1,3 和 2,3 。 但是像 1,2,3-1x 这样的聚合; 1,4,6-1x ; 1-1x 和 5,6-1x 也很有帮助。

您可以使用DataFrame.groupby('col').agg(func)itertools.combinations来获取所有 2 个标签组合,然后使用collections.Counter获取每个组合的出现次数。

from collections import Counter
from itertools import combinations
import pandas as pd

groups = df.groupby('post_ID').agg(lambda g: list(combinations(g, 2)))
combos = pd.DataFrame(
    Counter(groups.tag_ID.sum()).items(),
    columns=['tag_ID_combos', 'count']
    )

以下示例更改了您问题中的一些数据,以便至少有几个标签组合出现多次。

from collections import Counter
from itertools import combinations
import pandas as pd

data = [(1,1),(1,2),(1,3),(2,1),(2,3),(2,6),(3,1),(4,3),(4,6)]
df = pd.DataFrame(data, columns=['post_ID', 'tag_ID'])
print(df)
#    post_ID  tag_ID
# 0        1       1
# 1        1       2
# 2        1       3
# 3        2       1
# 4        2       3
# 5        2       6
# 6        3       1
# 7        4       3
# 8        4       6

groups = df.groupby('post_ID').agg(lambda g: list(combinations(g, 2)))
combos = pd.DataFrame(Counter(groups.tag_ID.sum()).items(), columns=['tag_ID_combos', 'count'])
print(combos)
#   tag_ID_combos  count
# 0        (1, 2)      1
# 1        (1, 3)      2
# 2        (2, 3)      1
# 3        (1, 6)      1
# 4        (3, 6)      2

如果您只想按 post_ID 聚合出现次数,这是一个解决方案。 此解决方案将根据您的示例进行计算(post_id == 1):

[1, 2, 3]: 1

并不是所有可能的组合:

[1, 2] = 1, [1, 3] = 1, [2, 3] = 1

df = df.groupby('post_ID')['tag_ID'].apply(list)
df = pd.DataFrame(df).reset_index()

# only if you want to throw out single occurrences
df = df[df['tag_ID'].map(len) > 1]

# cast the sorted lists to string
df['tag_ID_AS_STRING'] = [str(sorted(x)) for x in df['tag_ID']]
result = df['tag_ID_AS_STRING'].value_counts()

您可以使用group by 您可以使用以下

df.groupby(['post_ID', 'tag_ID']).count()

这将生成一个以组合为索引的表。

另一种方法是创建一个组合

df['combo'] = df[['post_ID', 'tag_ID']].agg(tuple, axis=1)

然后在combo字段上进行分组。

以上两个都需要更多的工作,我相信你可以从上面做。

您提到的第二种聚合非常容易获得:

df = pd.DataFrame({'post_ID': [1, 1, 1, 2, 2, 2, 3, 4, 4], 
                   'tag_ID': [1, 2, 3, 1, 4, 6, 1, 5, 6]})

df.groupby('post_ID').tag_ID.unique().value_counts()

# [1]          1
# [1, 4, 6]    1
# [1, 2, 3]    1
# [5, 6]       1
# Name: tag_ID, dtype: int64

您要求的第一种聚合不一致,这使得很难回答。 对于post_ID 1,您要求 1,2 、 1,3 和 2,3 ,而不计算元素与其自身的组合(1,1 、 2,2 等)。 然而对于post_ID 3,你确实说你想要 1-1x,这不是标签的组合。 如果后者是一个错误,你可以这样做,即使它不是很优雅:

首先,获取每个post_ID的组合:

import itertools

combs_df = df.groupby('post_ID').tag_ID\
    .apply(lambda x: list(itertools.combinations(x.tolist(), 2)))

combs_df

# post_ID
# 1    [(1, 2), (1, 3), (2, 3)]
# 2    [(1, 4), (1, 6), (4, 6)]
# 3                          []
# 4                    [(5, 6)]
# Name: tag_ID, dtype: object

现在,您通过将每一行的列表放在一个列表中来展平它们:

combs_lst = []
combs_df.apply(lambda x: combs_lst.extend(x))

combs_lst

# [(1, 2), (1, 3), (2, 3), (1, 4), (1, 6), (4, 6), (5, 6)]

现在,只需将列表作为熊猫系列并执行value_count

pd.Series(combs_lst).value_counts()

# (1, 4)    1
# (5, 6)    1
# (1, 6)    1
# (4, 6)    1
# (2, 3)    1
# (1, 3)    1
# (1, 2)    1
# dtype: int64

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM