Уникальное сочетание элементов между двумя векторами, максимизирующее общую сумму

У меня есть фрейм данных, содержащий все возможные комбинации между элементами двух векторов, и для каждой комбинации у меня есть соответствующая оценка. Я пытался найти эффективный способ найти подмножество уникальных пар с уникальными элементами (то есть элемент из одного вектора можно найти только один раз во всех парах), который максимизирует сумму баллов, соответствующих каждой комбинации. В качестве примера данных рассмотрим это df:

df = data.frame(Var1 = c("A", "B", "C"), Var2 = c("A", "C", "D"))
df = expand.grid(df$Var1, df$Var2)
df$score = c(1, 0.5, 2, 1, 0.5, 0.5, 1, 2, 1)
> df
  Var1 Var2 score
1    A    A   1.0
2    B    A   0.5
3    C    A   2.0
4    A    C   1.0
5    B    C   0.5
6    C    C   0.5
7    A    D   1.0
8    B    D   2.0
9    C    D   1.0
> 

Ожидаемый результат:

A  C  1
B  D  2
C  A  2

Обратите внимание, что у вас может быть перекрытие между элементами двух векторов, но опять же, каждый элемент из каждого вектора должен появляться только один раз. Кроме того, пара A A 1 разрешена и была бы возможна, но это сделало бы невозможным создание пары C A 2, которая увеличила бы общую сумму score. В качестве попытки я использовал этот лайнер с функциональностью из dplyr

df <- df %>% group_by(Var1) %>% slice(which.max(score)) %>% as.data.frame()

который производит:

> df
  Var1 Var2 score
1    A    A     1
2    B    D     2
3    C    A     2

что достаточно близко .. но повторяется A из второго вектора. Есть ли у вас какие-либо предложения? Заранее спасибо!


person Marius    schedule 19.03.2019    source источник
comment
У вас есть ничья, и он выбрал первую запись, поэтому он выбрал A A   -  person Sotos    schedule 19.03.2019
comment
Да, я так и подумал. Это поведение which.max, но мне нужно это преодолеть, и я пытался избежать написания некоторой рекурсивной функции для выполнения этой работы. Пытался также преобразовать его в матрицу со столбцами, являющимися уникальными элементами из одного вектора и строками из других, но затем я застрял, получая пары строка-столбец, максимизируя сумму   -  person Marius    schedule 19.03.2019


Ответы (1)


Что ж, в конце концов я нашел решение, основанное на венгерском алгоритме, реализованном в solve_LSAP функции clue Пакет R. Чтобы он работал, преобразуйте свой df в матрицу следующим образом:

df = matrix(sapply(df$score, function(x) x), nrow=length(unique(df$Var1)), ncol=length(unique(df$Var2)), dimnames = list(unique(df$Var1), unique(df$Var2)))

и примените функцию

df.res = solve_LSAP(df, maximum = T)
> df.res
Optimal assignment:
1 => 2, 2 => 3, 3 => 1

а затем вернуть фактические узлы или имена

df.res = cbind(rownames(df), colnames(df)[df.res])
> df.res
     [,1] [,2]
[1,] "A"  "C" 
[2,] "B"  "D" 
[3,] "C"  "A" 
> 

Тадааааам!

person Marius    schedule 20.03.2019