在Python中计算元素组合的频率

4

我有以下数据框:

enter image description here

我想要做的是计算元素组合的频率。例如:
  • 整个数据集中出现了8次伞
  • 洗涤剂出现了5次
  • (啤酒,尿布)出现了2次
  • (啤酒,牛奶)出现了2次
  • (伞,牛奶,啤酒)出现了2次
换句话说,我需要生成类似于这样的内容: enter image description here 统计所有单个和组合项的频率,并仅保留那些频率>=n的单个和组合项,其中n是任何正整数。对于此示例,假设n->{1,2,3,4}。
我一直在尝试使用以下代码:
# candidates itemsets
records = []

# generates a list of lists of products that were bought together (convert df to list of lists)
for i in range(0, num_records):
    records.append([str(data.values[i,j]) for j in range(0, len(data.columns))])
    
# clean list (delete NaN values)
records = [[x for x in y if str(x) != 'nan'] for y in records]

OUTPUT:
[['detergent'],
 ['bread', 'water'],
 ['bread', 'umbrella', 'milk', 'diaper', 'beer'],
 ['detergent', 'beer', 'umbrella', 'milk'],
 ['cheese', 'detergent', 'diaper', 'umbrella'],
 ['umbrella', 'water', 'beer'],
 ['umbrella', 'water'],
 ['water', 'umbrella'],
 ['diaper', 'water', 'cheese', 'beer', 'detergent', 'umbrella'],
 ['umbrella', 'cheese', 'detergent', 'water', 'beer']]

然后:

setOfItems = []
newListOfItems = []
for item in records:
    if item in setOfItems:
        continue
    setOfItems.append(item)
    temp = list(item)
    occurence = records.count(item)
    temp.append(occurence)
    newListOfItems.append(temp)

OUTPUT:

['detergent', 1]
['bread', 'water', 1]
['bread', 'umbrella', 'milk', 'diaper', 'beer', 1]
['detergent', 'beer', 'umbrella', 'milk', 1]
['cheese', 'detergent', 'diaper', 'umbrella', 1]
['umbrella', 'water', 'beer', 1]
['umbrella', 'water', 1]
['water', 'umbrella', 1]
['diaper', 'water', 'cheese', 'beer', 'detergent', 'umbrella', 1]
['umbrella', 'cheese', 'detergent', 'water', 'beer', 1]

正如您所看到的,它只计算整行(来自图像1)的频率,然而我的期望输出是出现在第二个图像中的输出。

目前你的item是一个条目列表而不是单个的条目,你可能需要使用两个for循环。先尝试将其正确运行在一个元素上,然后再逐步增加到更高层次。 - Shaido
1个回答

4

有趣的问题!我正在使用 itertools.combinations() 生成所有可能的组合,然后使用 collections.Counter() 统计每个组合出现的频率:

import pandas as pd
import itertools
from collections import Counter

# create sample data
df = pd.DataFrame([
    ['detergent', np.nan],
    ['bread', 'water', None],
    ['bread', 'umbrella', 'milk', 'diaper', 'beer'],
    ['umbrella', 'water'],
    ['water', 'umbrella'],
    ['umbrella', 'water']
])

def get_all_combinations_without_nan_or_None(row):
    # remove nan, None and double values
    set_without_nan = {value for value in row if isinstance(value, str)}
    
    # generate all possible combinations of the values in a row
    all_combinations = []
    for i in range(1, len(set_without_nan)+1):
        result = list(itertools.combinations(set_without_nan, i))
        all_combinations.extend(result)
        
    return all_combinations
    
# get all posssible combinations of values in a row
all_rows = df.apply(get_all_combinations_without_nan_or_None, 1).values
all_rows_flatten = list(itertools.chain.from_iterable(all_rows))

# use Counter to count how many there are of each combination
count_combinations = Counter(all_rows_flatten)

collections.Counter()文档:
https://docs.python.org/2/library/collections.html#collections.Counter

itertools.combinations()文档:
https://docs.python.org/2/library/itertools.html#itertools.combinations


它确切地做了我想要的事情,但是我正在尝试理解你的代码。我已经知道 itertools.combinations() 在做什么。实际上我之前就在使用它,但我认为我是以不同的方式使用它。我现在正在使用 itertools.combinations() 来传递我生成的列表的列表(实际上并没有做到我想要的效果),但我看到你正在使用 set_without_nan,但这个变量里面有什么并不是很清楚。你能帮我吗? - brenda
如果你想了解正在发生什么或变量的样子,我认为添加打印语句总是很方便的。因此,在函数get_all_cominations()中只需添加print(row)和print(set_without_nan)等语句,你就可以看到它的作用。它基本上获取数据框的行,循环遍历所有值,并仅保留不是nan的唯一值。然后,itertools.combinations创建一个包含行中所有可能单词组合的列表。使用变量的打印语句有助于使事情更清晰 :) - Sander van den Oord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接