给出一个带有布尔值的数据框,其中每行至少有三个True,每列至少有一个True,如果可能,我需要将这些列分配给N个不相交的组,每组中至少有三列。
例如N = 2
数据框:
a b c d e f
0 False True True True False False
1 True False True True True True
2 False False True False True True
唯一可能的结果:b,c,d和a,e,f
在较大的数据帧中可能有多个解决方案,我需要任何一种解决方案。如果解决方案需要,可以跳过列,但最好使用尽可能多的列。生成的组可以是任意大小,但不得少于三个。例如,对于N = 3和具有30列的数据帧,三个大小分别为9、3、11的组是有效结果。
无法分发的数据帧示例(在上面的示例中重置e1)
a b c d e f
0 False True True True False False
1 True False True True False True
2 False False True False True True
答案 0 :(得分:0)
我使用了RichieV的建议,并通过dancing links解决了该问题。
import pandas as pd
from typing import List, Tuple, Set
from itertools import combinations
def distribute_columns_by_triplets(df: pd.DataFrame, group_num: int,
result: List[Tuple[str]], tested: Set[Tuple[str]] = None) -> bool:
if not group_num:
return True
if not df.shape[0]:
return False
if df.shape[1] < 3 * group_num:
return False
if tested is None:
tested = set()
for index, row in df.iterrows():
positives = row[row].index
for i in range(positives.size, 2, -1):
current = combinations(positives, i)
for combination in current:
if combination in tested:
continue
tested.add(combination)
if distribute_columns_by_triplets(df.drop(columns=list(combination)),
group_num - 1, result, tested):
result.append(combination)
return True
df.drop(index, inplace=True)
return False
d = {
'a': [False, True, False],
'b': [True, False, False],
'c': [True, True, True],
'd': [True, True, False],
'e': [False, True, True],
'f': [False, True, True],
}
df = pd.DataFrame(d)
df['device_number'] = df.sum(axis=1)
df.sort_values(by='device_number', inplace=True)
df.drop('device_number', axis=1, inplace=True)
group_num = 2
result = []
if distribute_columns_by_triplets(df.copy(), group_num, result):
print(result)
else:
print('Failed')