簡體   English   中英

Pandas 按行中的三元組將列分配到不相交的組

[英]Pandas distribute columns to disjoint groups by triplets in rows

給定一個帶有布爾值的 dataframe,其中每行至少有三個 True,每列至少有一個 True,如果可能,我需要將列分配到 N 個不相交的組中,每組中至少有三列。

例如 N = 2

Dataframe:

        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

在較大的數據幀中可能有不止一種解決方案,我需要任何一種解決方案。 如果解決方案需要,可以跳過列,但最好使用盡可能多的列。 結果組可以是任意大小,但不少於三個。 例如,大小為 9、3、11 的 3 個組是 N=3 和具有 30 列的 dataframe 的有效結果。

dataframe 的示例,其中無法分發(在上面的示例中重置 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

我使用了 RichieV 的建議,並通過跳舞鏈接解決了這個問題。

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')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM