如何将许多列汇总成唯一的组合

How to summarize many columns into unique combinations

我有一个数据框,行中有设备列表,列中有许多需要设备结构的实验:

equipment  exp-1 exp-2 ... exp-n
equip-1    T     F         T
.          .     .         .
equip-n    T     F         F

设备名称是字符串,布尔值定义给定实验是否需要该设备。我试图将每个实验的所有不同设备要求压缩到通用列表中。最终目标是生成可用于该集合中多个实验的设备列表。

我通过执行以下步骤设法实现了这一目标:

  1. 转置数据帧并将所有布尔字段连接在一起
  2. 获取这些串联值的所有唯一实例
  3. 使用 .loc 遍历数据框并将合并后的 ID 分配给每一行
  4. 删除重复项。

最终结果如下所示:

experiment equip-1 ... equip-n equip-concat combo
exp-1      T           T       T...T        0
exp-2      F           F       F...F        1
exp-3      T           F       T...F        2

然后我能够再次转置它并将其粘贴回原始数据框中。所以我现在为每个组合都有一个布尔值列,显示一件设备是否属于它。

equipment  exp-1 exp-2 ... exp-n combo-1 ...combo-n
equip-1    T     F         T     T          F
.          .     .         .
equip-n    T     F         F     F          F

我还需要获取属于给定组合的所有实验的列表:

combo 1: exp-1, exp-2, exp4
combo 2: exp-3, exp-5
...

我通过对组合数据进行分组并打印出来实现了这一点。

是否有更简洁的方法从初始实验定义中获得我需要的结果?我的方法好像有点笨

编辑: 初始步骤的代码,一件事是我的初始实现将布尔值视为字符串。在这种情况下,配置是我试图提出的组合设备集。

dfexp = df.copy().set_index("equipment").transpose()
dfexpagg = dftests.agg("".join, axis=1)
dfexpagg.name = "Agg Gear"
dfexp["aggregated_gear"] = dfexpagg


unique_configs = dfexp["aggregated_gear"].unique()
for x, config in enumerate(unique_configs):
    dfexp.loc[dfexp["aggregated_gear"] == config, "Config"] = str(x)

dfconfigs = dfexp.set_index("Config"), drop=True).drop("aggregated_gear", axis=1).drop_duplicates().transpose()

我在 excel 中做了一个突出显示的示例,希望这有助于阐明最终目标。配置是我要生成的列。

我认为你不需要将它贴回原始数据框。

最终目标就像你描述的那样。所以formatting-wise,最接近和最清晰的是使用dictionary/JSON结构。例如,

# A map of equip_concat to list of experiment names
combo_map = {
    'TFFTFTT...' : ['exp_1', 'exp_4', ...]
     },
    'TFTFTFT...' : ...
}

所以只需遍历你的数据框并打印你的字典。

combo_map = {}
for index, row in df.iterrows():
    equip_concat = row['equip-concat']
    if equip_concat not in combo_map:
        combo_map[equip_concat] = []
    combo_map[equip_concat].append(row['experiment'])

print(combo_map)

遍历列:

df = pd.DataFrame([['T', 'F', 'T','T'], ['F', 'F', 'T','F'], ['F', 'F','T','F']], index = ['eq1', 'eq2', 'eq3'], columns = ['ex1', 'ex2', 'ex3', 'ex4'])

output = {}
for i, col in enumerate(df.columns):
    temp = df.index[df[col] == 'T'].tolist()
    if temp not in output.values():
        output[f'combo-{i}'] = temp

输出:

{'combo-0': ['eq1'], 'combo-1': [], 'combo-2': ['eq1', 'eq2', 'eq3']}