如何获取字典项组以覆盖python中的所有键?

时间:2019-04-24 03:06:50

标签: python group-by associations

我有如下所示的Python dict

d = {
    'AAA':['a', 'b', 'c'],
    'BBB':['b', 'c', 'd'],
    'CCC':['d', 'e', 'f', 'h', 'x'],
    'DDD':['d', 'f', 'g'],
    'EEE':['g','d','h','o']
}

dict的值是项。

我想让商品组涵盖所有dict键。

('b', 'c')组存在于AAABBB中。因此,该组可以覆盖AAABBB

可能的结果如下。

{('b', 'c'): ['AAA', 'BBB'],
 ('d', 'f'): ['CCC', 'DDD'],
 ('d', 'g'): ['EEE', 'DDD'],}

所有AAABBBCCCDDDEEE都可以用('b', 'c')('d', 'f')和{ {1}}。

FP-Growth和Apriori算法可能起作用。我如下尝试了('d', 'g'),但仍然无法获得这样的结果。

FP-Growth

输出为

import pyfpgrowth

d = [
    ['a', 'b', 'c'],
    ['b', 'c', 'd'],
    ['d', 'e', 'f', 'h', 'x'],
    ['d', 'f', 'g'],
    ['g','d','h','o']
]
#Use find_frequent_patterns to find patterns in baskets that occur over the support threshold:
patterns = pyfpgrowth.find_frequent_patterns(d, 2)
print(patterns)

FP-Growth和Apriori算法不能直接解决问题。除此之外,他们的表现也不佳。

我们有任何算法或lib可以执行此类任务吗?

1 个答案:

答案 0 :(得分:0)

这是使用熊猫的可能解决方案。 可以将包含键的组的长度限制在最小值和最大值之间。

import pandas as pd

d = {
    'AAA':['a', 'b', 'c'],
    'BBB':['b', 'c', 'd'],
    'CCC':['d', 'e', 'f', 'h', 'x'],
    'DDD':['d', 'f', 'g'],
    'EEE':['g','d','h','o']
}


for k, i in d.items():
    df1 = pd.DataFrame(columns=list(i), index=[k])
    df1[:]=True
    try:
        df=df.append(df1, sort=True)
    except:
        df=df1.copy()

只要知道发生了什么,中间数据帧df就是这样的表:

    a    b    c    d    e    f    g    h    o    x
AAA True True True NaN  NaN  NaN  NaN  NaN  NaN  NaN
BBB NaN  True True True NaN  NaN  NaN  NaN  NaN  NaN
CCC NaN  NaN  NaN  True True True NaN  True NaN  True
DDD NaN  NaN  NaN  True NaN  True True NaN  NaN  NaN
EEE NaN  NaN  NaN  True NaN  NaN  True True True NaN

然后,您将转置此数据框并提取组,如下面的代码所示;您可以为每个键组中所需的项数设置限制。 覆盖每个组的元素数量没有限制。因此,一组键可以被单个元素(结果)覆盖。 这是一个可能的解决方案,因为除非指定了其他约束,否则您的问题还有很多其他解决方案。 该代码还检查了所有键是否都受给定约束的解决方案覆盖。

# set min and max number of items in each tuple of keys
min = 2
max = 3

df=df.fillna(False)

dft=df.transpose()

dft['sum'] = dft[:].sum(axis=1)

dft1 = dft[(dft['sum']>=min) & (dft['sum']<=max)]
dft1 = dft1.drop('sum', axis=1)

g = lambda a,b:[x for x, y in zip(tuple(a), tuple(b)) if y == True]

c=dft1.columns
dft1['groups'] = dft1.apply(lambda x: g(c, x), axis=1)
dft1['groups'] = dft1['groups'].apply(tuple)

grouped=dft1.groupby('groups')

final = dict()
key_covered = []
for key, item in grouped:
    lkey = list(key)
    if not set(lkey).issubset(key_covered):
        final[key] = tuple(item.index)
        key_covered += key

print('Result:')
for k,i in final.items():
    print(i, end=': ')
    print(k)

print('Keys covered')
print(key_covered)

# Check if result covers all keys
if not set(key_covered).issubset(d.keys()):
    print('Initial dict is not covered with this constrains')

每个键组中的最小项目数等于2,最大数量为3,最终结果将是:

Result:
('b', 'c'): ('AAA', 'BBB')
('f',): ('CCC', 'DDD')
('h',): ('CCC', 'EEE')
Keys covered
['AAA', 'BBB', 'CCC', 'DDD', 'CCC', 'EEE']

如果每个键组中的最小项目数等于2,最大数量等于4,则最终结果将是:

Result:
('b', 'c'): ('AAA', 'BBB')
('d',): ('BBB', 'CCC', 'DDD', 'EEE')
Keys covered
['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'EEE']