微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算给定数据框中项集的频率

如何解决计算给定数据框中项集的频率

我有以下数据框,

data = pd.read_csv('sample.csv',sep=',')

Dataframe

我需要搜索集合中存在的项集的频率。例如:

itemsets = {(143,157),(143,166),(175,178),190)}

这应该搜索数据帧中每个元组的频率(尝试实现 Apriori 算法)。我在如何单独处理数据框中的元组以及搜索元组而不是数据中的单个条目方面遇到了特别大的麻烦。

更新 1

例如数据框是这样的:

39,120,124,205,401,581,704,814,825,834
35,39,712,733,759,854,950
39,422,449,857,895,937,954,964

更新 2

只有当元组中的所有值都存在于特定行中时,函数才应该增加元组的计数。 例如,如果我搜索 (39,205),它应该返回 2 的频率,因为其中 2 行同时包含 39205(第一行和第二行)。

解决方法

此函数将返回一个字典,其中包含元组计数在数据框的整个行中出现的次数。

from collections import defaultdict
def count(df,sequence):
    dict_data = defaultdict(int)
    shape = df.shape[0]
    for items in sequence:
        for row in range(shape):
            dict_data[items] += all([item in df.iloc[row,:].values for item in items])
    return dict_data

您可以将数据框和集合传递给 count() 函数,它会为您返回数据框整行中元组的出现次数,即

>>> count(data,itemsets)
defaultdict(<class 'int'>,{(39,205): 2})

您可以使用 defaultdict 方法轻松将其从 dict() 更改为字典,即

>>> dict(count(data,itemsets))
{(39,205): 2}

但它们的工作方式仍然相同。

,
itemsets = {(39,205),(39,205,401),(143,157),166),(175,178),190)}

x = [[39,120,124,401,581,704,814,825,834],[35,39,712,733,759,854,950],[39,422,449,857,895,937,954,964]]

data = pd.DataFrame(x)

for itemset in itemsets:
    print(itemset)
    count = 0
    for i in range(len(data)):
        flag = True
        for item in itemset:
            if item not in data.loc[i].value_counts():
                flag = False
        if flag:
            count += 1
    print(count)

按照评论中的建议进行编辑以考虑抽象项集长度(非常感谢您提供有用的见解)。

,

首先,由于对问题的含义存在一些误解,因此本答案回答了“如何计算项目集中每个项目至少出现一次的行数?”的问题。


对于数据框中的每个row,我们可以使用

决定是否将其计入频率
all(item in row for item in items)

其中 items 是项集,例如 (39,205)

我们可以使用 DataFrame.itertuples 遍历所有行,因此对于每个项目集 items,其频率为

sum(1 for row in map(set,df.itertuples(name=None)) if all(item in row for item in items))

(我们使用 map(set,...) 将元组转化为集合,这不是必需的,但可以提高效率)

最后,我们遍历 itemsets 中的所有项目集并将结果存储在字典中,其中键是项目集,值是频率:

{items: sum(1 for row in map(set,df.itertuples(name=None)) if all(item in row for item in items)) for items in itemsets}

输出: 您提供的案例的输出是 {(39,205): 2}

如果您不喜欢单行版本,可以将算法扩展为多行,如下所示:

d = {}  # output dictionary
for items in itemsets:
    frequency = 0
    for row in df.itertuples(name=None):
        row = set(row)  # done for efficiency
        for item in items:
            if item not in row:
                break
        else:  # no break
            frequency += 1
    d[items] = frequency

有关 for ... else 的其他信息可以在 this answer

中找到

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。