带替换的Python条件枚举

2024-06-07 01:26:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个名为fleet_df的数据帧,看起来像这样:

Vehicle_ID     Capacity
001            5
002            6
003            10

我还有a变量总需求量

total_demand = 55

我想要的是列举所有更换车辆的组合,只要总容量大于或等于总容量,且小于或等于总容量的两倍

示例输出:

Scenario     Vehicle_IDs                           Total_Capacity
1            001, 001, 001, 003, 003, 003, 003     55
2            003, 003, 003, 003, 003, 003, 003     70
...

我原以为这样会奏效,但到目前为止运气不佳:

enumerate(i for i in fleet_df['Capacity'].values.tolist() if (total_demand <= i) and (i <= total_demand * 2))

我错过了什么


Tags: 数据idids示例dftotal容量capacity
1条回答
网友
1楼 · 发布于 2024-06-07 01:26:05

我认为您可能可以这样做—获取行索引的组合,对于每个行组合,找到容量总和,并根据条件对其进行过滤

fleet_df = pd.DataFrame({'Vehicle_ID': ['001', '002', '003'],
                         'Capacity': [5, 6, 10]})
# Set the index as 'Vehicle_ID'
fleet_df.set_index(['Vehicle_ID'], inplace=True)
total_demand = 55
n = 10
final_df = pd.DataFrame([])

for i in range(1, n):
    comb_indices = list(comb for comb in itertools.combinations_with_replacement(fleet_df.index, r=i))
    comb_rows = pd.DataFrame([fleet_df.loc[comb, 'Capacity'].sum() for comb in comb_indices],
                             index=comb_indices, columns=['Total Capacity'])
    final_df = final_df.append(comb_rows[(comb_rows['Total Capacity'] >= total_demand) & (comb_rows['Total Capacity'] <= 2*total_demand)])


final_df = final_df.rename_axis('Vehicle_IDs').reset_index().rename_axis('Scenarios')
print(final_df)

说明:

线路

list(comb for comb in itertools.combinations_with_replacement(fleet_df.index, r=i))

将获得来自fleet_df的所有索引与来自0 to ni元素的组合。因此,使用i=2您将拥有comb_indicesas

[('001', '001'), ('001', '002'), ('001', '003'), ('002', '002'), ('002', '003'), ('003', '003')]

接下来,创建一个临时数据帧comb_rows,该行与组合comb_indices中的索引匹配

comb_rows = pd.DataFrame([fleet_df.loc[comb, 'Capacity'].sum() for comb in comb_indices], index=comb_indices, columns=['Total Capacity'])

最后,将总容量满足所需总需求的匹配行追加到final_df

comb_rows[(comb_rows['Total Capacity'] >= total_demand) & (comb_rows['Total Capacity'] <= 2*total_demand)]

一旦你有了final_df,你可以根据需要重命名索引

这里n的值是每个组合中的元素数。当n增加时,我不知道这将是一个有效的解决方案。而且n取决于total_demand,因为在total_demand值控制下的重复可能是无限的。由于total_demand值的增加幅度远大于车辆的单个容量,因此n值也应更高,以满足所有组合的要求。 n的范围可以限定为total_demand/max(capacity)(2*total demand)/min(capacity)。我想你应该得到这里面所有的匹配组合。因此,在本例中,n的范围将是

min_comb = int(total_demand/max(fleet_df['Capacity'].to_list()))
max_comb = int((2*total_demand)/min(fleet_df['Capacity'].to_list()))
for i in range(min_comb, max_comb+1):
    ...
    ...

最终结果:

                                             Vehicle_IDs  Total Capacity
Scenarios                                                               
0                         (001, 003, 003, 003, 003, 003)              55
1                         (002, 003, 003, 003, 003, 003)              56
2                         (003, 003, 003, 003, 003, 003)              60
3                    (001, 001, 001, 003, 003, 003, 003)              55
4                    (001, 001, 002, 003, 003, 003, 003)              56
...                                                  ...             ...
71         (002, 002, 002, 002, 003, 003, 003, 003, 003)              74
72         (002, 002, 002, 003, 003, 003, 003, 003, 003)              78
73         (002, 002, 003, 003, 003, 003, 003, 003, 003)              82
74         (002, 003, 003, 003, 003, 003, 003, 003, 003)              86
75         (003, 003, 003, 003, 003, 003, 003, 003, 003)              90
...                                                      ...         ...
828        (001, 001, 001, 001, 001, 001, 001, 001, 001, ...         107
829        (001, 001, 001, 001, 001, 001, 001, 001, 001, ...         108
830        (001, 001, 001, 001, 001, 001, 001, 001, 001, ...         109
831        (001, 001, 001, 001, 001, 001, 001, 001, 001, ...         110
832        (001, 001, 001, 001, 001, 001, 001, 001, 001, ...         110

[833 rows x 2 columns]

对于更高的值,可能有更好的解决方案,但这应该适用于示例数据集

相关问题 更多 >