#python #numpy #dictionary
Вопрос:
У меня есть массив диктов с одинаковыми ключами, и для каждого ключа у меня есть массив значений, как показано в примере ниже:
dict_arr = np.array([{'x': np.array([1,2,3]), 'y': np.array([1,4,9])}, {'x': np.array([4,5,6]), 'y': np.array([16,25,64])}])
Что мне нужно сделать, так это объединить все в один диктант, но под слиянием я подразумеваю, что я должен объединить значения массивов из одного и того же ключа. Ожидаемым результатом для примера будет:
{'x': array([1., 2., 3., 4., 5., 6.]), 'y': array([ 1., 4., 9., 16., 25., 64.])}
Код, который я сделал, был следующим:
new_dict = {'x': np.array([]), 'y': np.array([])} for dict_ in dict_arr: for key, value in dict_.items(): new_dict[key] = np.append(new_dict[key], value) print(new_dict)
и это дает мне ожидаемый результат, но мне интересно, есть ли более разумный способ сделать это, когда я просто объединяю » x » из всех диктов, вместо того, чтобы повторять каждый из них в каждом ключе и значении и обновлять значение моего нового дикта.
Примечание: мой реальный массив предсказывает порождается сбора данных борту, которые не могут приобрести более 1024 сведения на канал, поэтому каждый словарь в списке, кроме последнего, имеет от одного до трех матриц с разрешением 1024 плавает ценности каждого, и число предсказывает я обычно составляет порядка 400 тысяч.
Комментарии:
1. массивы numpy на самом деле не предназначены для такого рода структуры данных. И зацикливание звучит как ваш лучший вариант…
2. Я также должен отметить, что
dict_array
это то, что не имеет смысла. Размещение объектов Python в anumpy.ndarray
в основном создает менее эффективный список Python. Что бы я сделал, если данные могут быть огромными, так это использовал список, чтобы у вас было что-то вроде{'x':[...], ...}
того, чтобы вы могли эффективно расширять этот список, а затем, наконец, преобразовать его в массив numpy внутренне, если необходимо. Потомуnp.append(new_dict[key], value)
что в цикле есть анти-шаблон3. В любом случае, нет способа сделать то, что вы хотите, без итерации
Ответ №1:
Добавление списка выполняется быстрее, чем повторение np.append
:
In [44]: dict_arr = np.array([{'x': np.array([1,2,3]), 'y': np.array([1,4,9])}, {'x': np.array([4,5,6]), 'y': np ...: .array([16,25,64])}]) In [45]: new_dict={'x':[], 'y':[]} In [46]: for dict in dict_arr: ...: for key,value in dict.items(): ...: new_dict[key].append(value) ...: In [47]: new_dict Out[47]: {'x': [array([1, 2, 3]), array([4, 5, 6])], 'y': [array([1, 4, 9]), array([16, 25, 64])]} In [48]: newer = {key:np.hstack(value) for key,value in new_dict.items()} In [49]: newer Out[49]: {'x': array([1, 2, 3, 4, 5, 6]), 'y': array([ 1, 4, 9, 16, 25, 64])}
defaultdict
может упростить создание такого рода словарей:
In [55]: from collections import defaultdict In [56]: dd = defaultdict(list) In [58]: for dict in dict_arr: ...: for k,v in dict.items(): ...: dd[k].append(v) ...: In [59]: dd Out[59]: defaultdict(list, {'x': [array([1, 2, 3]), array([4, 5, 6])], 'y': [array([1, 4, 9]), array([16, 25, 64])]}) In [60]: newer = {key:np.hstack(value) for key,value in dd.items()} In [61]: newer Out[61]: {'x': array([1, 2, 3, 4, 5, 6]), 'y': array([ 1, 4, 9, 16, 25, 64])}
Поскольку ключи одинаковы, мы можем использовать values
:
In [54]: list(zip(*[list(dict.values()) for dict in dict_arr])) Out[54]: [(array([1, 2, 3]), array([4, 5, 6])), (array([1, 4, 9]), array([16, 25, 64]))]
и подтверждаю:
In [63]: [np.hstack(i) for i in zip(*[list(dict.values()) for dict in dict_arr])] Out[63]: [array([1, 2, 3, 4, 5, 6]), array([ 1, 4, 9, 16, 25, 64])]
Это все еще нужно вернуть в dict
форму
In [67]: {k:v for k,v in zip(dict_arr[0], Out[63])} Out[67]: {'x': array([1, 2, 3, 4, 5, 6]), 'y': array([ 1, 4, 9, 16, 25, 64])}
Ответ №2:
Я не уверен на 100%, что это будет более эффективно для вашего варианта использования (на самом деле, есть большая вероятность, что это будет медленнее, так как мы все еще зацикливаемся…), но я рекомендую попробовать и рассчитать время на ваших полных данных:
import pandas as pd import numpy as np dict_arr = np.array([{'x': np.array([1,2,3]), 'y': np.array([1,4,9])}, {'x': np.array([4,5,6]), 'y': np.array([16,25,64])}]) df = pd.DataFrame.from_records(dict_arr) df.apply(np.hstack, result_type='reduce').to_dict() # {'x': array([1, 2, 3, 4, 5, 6]), 'y': array([ 1, 4, 9, 16, 25, 64])}