Сохраните значения для каждого ключа в виде массива в словаре - PullRequest
2 голосов
/ 21 марта 2019

Я хотел бы нормализовать все значения в словаре data и снова сохранить их в другом словаре с теми же ключами, и для каждого ключа значения должны быть сохранены в массиве 1D, поэтому я сделал следующее:

>>> data = {1: [0.6065306597126334], 2: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 3: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 4: [0.6065306597126334, 0.6065306597126334]}

>>> norm = {k: [v / sum(vals) for v in vals] for k, vals in data.items()} 

>>> norm
{1: [1], 2: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 3: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 4: [0.5, 0.5]}

Теперь предположим, что словарь data содержит только нулевое значение для одного из его ключей, например, значение первого ключа 1:

>>> data = {1: [0.0], 2: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 3: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 4: [0.6065306597126334, 0.6065306597126334]}

тогда нормализация значений этого словаря приведет к [nan] значениям из-за деления на ноль

>>> norm = {k: [v / sum(vals) for v in vals] for k, vals in data.items()}

__main__:1: RuntimeWarning: invalid value encountered in double_scalars
>>> norm
{1: [nan], 2: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 3: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 4: [0.5, 0.5]}

Поэтому я вставил if statement, чтобы преодолеть эту проблему, но не могу сохранить значения для каждого ключа в виде массива идентификаторов

код

>>> norm = {}
>>> for k, vals in data.items():
...     values = []
...     if sum(vals) == 0:
...        values.append(list(vals))
...     else:
...          for v in vals:
...              values.append(list([v/sum(vals)]))
...     norm[k]=values
... 
>>> norm
{1: [[1.0]], 2: [[0.4498162176582741], [0.4498162176582741], [0.10036756468345168]], 3: [[0.4498162176582741], [0.4498162176582741], [0.10036756468345168]], 4: [[0.5], [0.5]]}

Я хотел бы получить словарь norm как

norm = {1: [1.0], 2: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 3: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 4: [0.5, 0.5]}

Кроме того, для словаря data, хотя он содержит нулевое значение единицы, если он является ключом, существует ли лучшее решение для его нормализации, поскольку я считаю, что мое решение неэффективно!

P.S .: Я попытался в конце цикла for norm[k]= np.array(values) вместо norm[k]=values, но результат был не таким, как требуется.

Ответы [ 3 ]

1 голос
/ 21 марта 2019

Как уже упоминалось в ответе, extend может быть использовано для решения вашей проблемы.Если вы хотите использовать append, вы можете взять первый элемент ваших списков.

norm = {}
for k, vals in data.items():
    values = []
    if sum(vals) == 0:
        values.append(vals[0])
    else:
        for v in vals:
            values.append([v / sum(vals)][0])
    norm[k] = values

См. разница между методами добавления и расширения в Python для примера добавления против расширения

Что касается оптимизации.Полное удаление циклов for будет невозможно, но вы можете сократить свое решение, сохраняя читабельность:

norm = {}
for k, vals in data.items():
    if sum(vals) == 0:
        norm[k] = vals
    else:
        norm[k] = [x / sum(vals) for x in vals]
1 голос
/ 21 марта 2019

append как упомянуто выше добавляет элемент в список, и этот элемент может быть списком, поэтому у вас в настоящее время есть список в списке. В идеале вы должны использовать extend, который объединяет первый список с другим списком.

0 голосов
/ 21 марта 2019

Ваше понимание диктовок / списков не выполняется, когда sum(vals) == 0:

>>> data = {1: [0.0], 2: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 3: [0.6065306597126334, 0.6065306597126334, 0.1353352832366127], 4: [0.6065306597126334, 0.6065306597126334]}
>>> {k: [v / sum(vals) for v in vals] for k, vals in data.items()}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <dictcomp>
  File "<stdin>", line 1, in <listcomp>
ZeroDivisionError: float division by zero

Вы можете ввести троичное выражение для обработки регистра:

>>> {k: [v / sum(vals) if sum(vals)!=0 else 1.0 for v in vals] for k, vals in data.items()}
{1: [1.0], 2: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 3: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 4: [0.5, 0.5]}

Если вы хотите избежать оценки sum(vals) несколько раз:

>>> {k: [v / s if s!=0 else 1.0 for v in vals] for k,vals,s in ((k, vals, sum(vals)) for k, vals in data.items())}
{1: [1.0], 2: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 3: [0.4498162176582741, 0.4498162176582741, 0.10036756468345168], 4: [0.5, 0.5]}

((k, vals, sum(vals)) for k, vals in data.items()) - генератор, который возвращает k, vals и sum(vals) для каждого элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...