Если я правильно понимаю, вам нужен каждый порядок сортировки каждый раз, когда вы достигаете максимума на col1
.
df.groupby(['col0'], as_index=False)['col1'].max()
df
, как вы сделали df
: pd.merge(df, col1_max_groups)
DataFrame
новыми значениями Полный пример :
col1_max_groups = df.groupby(['col0'], as_index=False)['col1'].max()
deduped = df.sort_values(['col0', 'col1', 'abs(col1 - col2)', 'col2'],
ascending=[True, True, True, False]) \
.drop_duplicates(['col0', 'col1']) \
.set_index(['col0', 'col1'])
update = pd.merge(df, col1_max_groups) \
.sort_values(['col0', 'col1', 'abs(col1 - col2)', 'col2'],
ascending=[True, True, False, False]) \
.drop_duplicates(['col0', 'col1'])
deduped.update(update.set_index(['col0', 'col1']))
deduped.reset_index()
# returns
# col0 col1 col2 abs(col1 - col2)
# A 1 2 1
# A 2 3 1
# A 3 4 1
# A 4 1 3
# B 2 3 1
# B 3 4 1
# B 4 5 1
# B 5 2 3
Изменение сценария MSI_SetProperty.js дает
// MSI_SetActionSequence.js <msi-file> <table> <action> <sequence>
// Performs a post-build fixup of an msi to set the specified table/action/sequence
// Constant values from Windows Installer SDK
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1;
var msiViewModifyUpdate = 2;
var msiViewModifyAssign = 3;
var msiViewModifyReplace = 4;
var msiViewModifyDelete = 6;
if (WScript.Arguments.Length != 4)
{
WScript.StdErr.WriteLine("Usage: " + WScript.ScriptName + " file table action sequence");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var table = WScript.Arguments(1);
var action = WScript.Arguments(2);
var sequence = parseInt(WScript.Arguments(3));
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
WScript.StdOut.WriteLine("Looking for action:" + action);
try
{
var sql = "SELECT Action, Sequence FROM " + table + " WHERE Action = '" + action + "'";
var view = database.OpenView(sql);
view.Execute();
var record = view.Fetch();
if (record)
{
while (record)
{
WScript.StdOut.Write("Found: " + record.StringData(0) + ", " + record.StringData(1) + ", " + record.StringData(2));
if (record.IntegerData(2) != sequence)
{
WScript.StdOut.WriteLine(" - changing to " + sequence);
record.IntegerData(2) = sequence;
view.Modify(msiViewModifyUpdate,record);
}
else
WScript.StdOut.WriteLine(" - OK");
record = view.Fetch();
}
view.Close();
database.Commit();
}
else
{
view.Close();
throw("Warning - Could not find " + table + "." + action);
}
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Назвать этот сценарий для выполнения изменения в последовательности действий, упомянутой выше Вас, поместило бы следующее в пакетный файл и вызов, которые из сообщения создают событие, например, PostBuildEvent = $ (ProjectDir) PostBuild.bat
cscript.exe MSI_SetActionSequence.js YOURINSTALLER.MSI InstallExecuteSequence RemoveExistingProducts 1525