Возьмите строку кадра данных, который в сумме дает заданное значение - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть следующий фрейм данных:

enter image description here

Для чего нужно брать пользователей из столбца id, пока общее значение не сложится до заданного значения, например 14 . Как я могу выбрать строки для эффективного выполнения этого условия?

Вот данные, которые я использую для примера:

{'id': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},
 'valor': {0: 5.690813772729765,
  1: 5.502473982705203,
  2: 7.341171631905721,
  3: 6.792634352953639,
  4: 3.3972025109972535,
  5: 3.417867922325758,
  6: 7.336228970419381,
  7: 0.048008919685266216,
  8: 2.365638019103776,
  9: 0.9593678139592221}}

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Вот решение перебор с использованием генератора с itertools.combinations:

from itertools import chain, combinations
from operator import itemgetter

d = dict(zip(d['id'].values(), d['valor'].values()))  # restructure dictionary

def gen_ids_sum(d):
    for id_tup in chain.from_iterable(combinations(d, i) for i in range(1, len(d))):
        yield id_tup, sum(map(d.__getitem__, id_tup))

ids, val_sum = min(gen_ids_sum(d), key=lambda x: (x[1] <= 14, abs(x[1] - 14)))

print(ids, val_sum)

(1, 7, 8, 10) 14.034419476793634

Настройка

d = {'id': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},
     'valor': {0: 5.690813772729765, 1: 5.502473982705203, 2: 7.341171631905721,
               3: 6.792634352953639, 4: 3.3972025109972535, 5: 3.417867922325758,
               6: 7.336228970419381, 7: 0.048008919685266216, 8: 2.365638019103776,
               9: 0.9593678139592221}}
0 голосов
/ 03 ноября 2018

Ближайшее значение можно найти с помощью:

def options(valor, i, total, maximum, lowest, lst_ids):
    if total > maximum:
        return total, lst_ids
    ids = ''
    for j in range(i, len(valor)):
        lst_ids += ', ' + str(valor[j][1])
        new_score, new_ids = options(valor, j + 1, total + valor[j][0], maximum, lowest, lst_ids)
        lst_ids = lst_ids.replace(', ' + str(valor[j][1]), '')
        if new_score < lowest:
            lowest = new_score
            ids = new_ids
    return lowest, ids


data = {'id': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},
        'valor': {0: 5.690813772729765, 1: 5.502473982705203, 2: 7.341171631905721, 3: 6.792634352953639,
                  4: 3.3972025109972535, 5: 3.417867922325758, 6: 7.336228970419381, 7: 0.048008919685266216,
                  8: 2.365638019103776, 9: 0.9593678139592221}}

valor = [(data['valor'][i], data['id'][i]) for i in data['valor']]
closest_score, ids = options(valor, 0, 0, 14, 1e10, '')
ids = ids[2:]
print(closest_score, ids)

Возвращает 14.034419476793634 1, 7, 8, 10, первая часть является наименьшим значением, вторая часть - идентификаторы, необходимые для получения этой оценки. Если вы хотите получить действительные числа в виде целых чисел, вы можете просто использовать:

ids = [int(i) for i in ids.split(', ')]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...