我是python新手,有一个简单LP问题的输出。
在这个问题中,几个PART's组成一个House,几个House组成一个society。有房子和社会层面的交付目标。如果在任何一个级别上没有达到交付目标,那么差的部分将被替换(替换=Y)为交付50个单位的部分。
解决方案是最优化的,但是,我们没有能力替换,所以,我想优先替换。
例如:我有能力进行3次替换,而解决方案给出了7次替换。
我们能否根据优先级对解决方案进行后处理,以获得3个替换。
给定=3个替换maxpriority=S3(社会3),H2,H1,S2。
我的输出是在U,R和A处进行替换,其他的保持原样,这在python中可以做到吗,还是说在python中做不到(这样的话,我可以用excel宏)。
编辑
Raw data:
data = [
{'Part': 'A', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 10, 'Replaced': 'Y'},
{'Part': 'B', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 30, 'Replaced': ''},
{'Part': 'C', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'D', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'E', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'F', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'G', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'H', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'I', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'J', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'K', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'L', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'M', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'N', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'O', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 20, 'Replaced': 'Y'},
{'Part': 'P', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'Q', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'R', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 20, 'Replaced': 'Y'},
{'Part': 'S', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'T', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'U', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 15, 'Replaced': 'Y'},
{'Part': 'V', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'W', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},
]
house_targets = {'H1': 140,
'H2': 160,
'H3': 120,
'H4': 110,
'H5': 120,
'H6': 115,
'H7': 105,
}
society_targets = {'S1': 330,
'S2': 500,
'S3': 250}
df = pd.DataFrame(data)
for house, target in house_targets.items():
df.loc[df['House'] == house, 'House_Target'] = target
for society, target in society_targets.items():
df.loc[df['Society'] == society, 'Society_Target'] = target
replacement_value = 50
df.loc[df['Replaced'] == 'Y', 'replacement_value'] = replacement_value - df['Present_Delivery']
df['replacement_value'].fillna(0, inplace=True)
在pandas中,解决方案是直接的。你只需要把给定优先级的右列切开,然后排序就可以了。大部分代码只是包装器的锅炉板。
import pandas as pd
class ReplacementConstraint:
def __init__(self, df: pd.DataFrame, *, max_replacements: int, priority: list):
assert isinstance(df, pd.DataFrame)
self.df = df
self.max_replacements = max_replacements
self.priority = priority
self.result = pd.DataFrame()
@staticmethod
def parse_priority(prio_str):
"""Mapping priority String to column"""
col_map = {'H': 'House',
'S': 'Society'}
return col_map[prio_str[0]]
def calculate(self):
"""Sort slices of dataframe with respect to priorities and append to self.result"""
for prio in self.priority:
col = self.parse_priority(prio)
mask = (self.df['Replaced'] == 'Y') & (self.df[col] == prio)
result_tmp = self.df[mask].sort_values('replacement_value', ascending=False)
self.result = pd.concat([self.result, result_tmp])
self.result = self.result.iloc[:self.max_replacements]
给定一个数据帧 df
(见下图)你可以将包装器作为。
wrapper = ReplacementConstraint(df, max_replacements=3, priority=['S3', 'H2', 'H1', 'S2'])
wrapper.calculate()
print(wrapper.result)
该解决方案看起来像:
Part House Society ... House_Target Society_Target replacement_value
20 U H7 S3 ... 105.0 250.0 35.0
17 R H6 S3 ... 115.0 250.0 30.0
0 A H1 S1 ... 140.0 330.0 40.0
数据框数据的输入花了我大部分时间。下次请考虑发文字而不是图片。我把它贴在这里,所以如果别人想贴另一个解决方案,她不需要再打一次。此外,通过发布数据框架,我的解决方案是 重现性.
data = [
{'Part': 'A', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 10, 'Replaced': 'Y'},
{'Part': 'B', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 30, 'Replaced': ''},
{'Part': 'C', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'D', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'E', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'F', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'G', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'H', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'I', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'J', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'K', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'L', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'M', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
{'Part': 'N', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'O', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 20, 'Replaced': 'Y'},
{'Part': 'P', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'Q', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'R', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 20, 'Replaced': 'Y'},
{'Part': 'S', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'T', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},
{'Part': 'U', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 15, 'Replaced': 'Y'},
{'Part': 'V', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
{'Part': 'W', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},
]
house_targets = {'H1': 140,
'H2': 160,
'H3': 120,
'H4': 110,
'H5': 120,
'H6': 115,
'H7': 105,
}
society_targets = {'S1': 330,
'S2': 500,
'S3': 250}
df = pd.DataFrame(data)
for house, target in house_targets.items():
df.loc[df['House'] == house, 'House_Target'] = target
for society, target in society_targets.items():
df.loc[df['Society'] == society, 'Society_Target'] = target
replacement_value = 50
df.loc[df['Replaced'] == 'Y', 'replacement_value'] = replacement_value - df['Present_Delivery']
df['replacement_value'].fillna(0, inplace=True)
这可以通过使用 join
, combine_first
和 sort
:
priority = ["S3", "H2", "H1", "S2"]
priority = pd.Series(range(len(priority)), index=priority, name="priority")
df["priority"] = df.join(priority, on="Society").priority.combine_first(df.join(priority, on="House").priority)
result = df[df.replacement_value > 0] .sort_values("priority").head(3)
print(result)
结果:
Part House Society Present_Delivery Replaced House_Target Society_Target replacement_value priority
17 R H6 S3 20 Y 115.0 250.0 30.0 0.0
20 U H7 S3 15 Y 105.0 250.0 35.0 0.0
0 A H1 S1 10 Y 140.0 330.0 40.0 2.0