слияние словарей в python - PullRequest
       5

слияние словарей в python

2 голосов
/ 17 февраля 2010

Извините за очень общее название, но я постараюсь быть как можно более конкретным.

Я работаю над приложением для анализа текста. У меня есть большое количество пар ключ-значение в форме ((word, corpus) -> occurence_count) (все целые числа), которые я храню в нескольких словарях python (tuple-> int). Эти значения распределены по нескольким файлам на диске (я их мариновал). Чтобы разобраться в данных, мне нужно объединить эти словари. По сути, мне нужно найти способ найти все вхождения определенного ключа во всех словарях и сложить их, чтобы получить общее количество.

Если я загружаю более одного словаря за раз, у меня заканчивается память, из-за чего мне пришлось разбить их в первую очередь. Когда я попытался, я столкнулся с проблемами производительности. В настоящее время я пытаюсь сохранить значения в БД (mysql), обрабатывая несколько словарей одновременно, поскольку mysql обеспечивает блокировку на уровне строк, что является как хорошим (так как это означает, что я могу распараллелить эту операцию), так и плохим (так как он замедляется запросы на вставку)

Какие у меня есть варианты? Является ли хорошей идеей написать словарь, основанный частично на диске, чтобы я мог обрабатывать слова по одному? Со стратегией замены LRU? Есть ли что-то, что я совершенно не замечаю?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 17 февраля 2010

Существует дискообразный словарь - см. Модуль shelve . Ключи в полке должны быть строками, но вы можете просто использовать str на своих кортежах для получения эквивалентных строковых ключей; плюс, я читаю ваш Q как означающий, что вы хотите только word в качестве ключа, так что это даже проще (или str - или, для словарей <4GB, struct.pack - будет хорошо). </p>

Хороший реляционный движок (особенно PostgreSQL) будет вам полезен, но обработка одного словаря за один раз для объединения каждого вхождения слова по всем корпусам в объект shelf также должна быть в порядке (не так быстро, но проще код, поскольку shelf очень похож на dict, за исключением ограничения типа для ключей [[и предостережения для изменяемых значений, но поскольку ваши значения int s, которые не должны вас касаться).

0 голосов
/ 17 февраля 2010
  1. Если я правильно понял ваш вопрос, и у вас есть целочисленные идентификаторы для слов и корпусов, то вы можете добиться некоторой производительности, переключившись с dict на список или, что еще лучше, на массив numpy. Это может раздражать!

    По сути, вам нужно заменить кортеж одним целым числом, которое мы можем назвать newid. Вы хотите, чтобы все новые слова соответствовали слову, паре корпусов, поэтому я посчитал бы слова в каждом корпусе, а затем для каждого корпуса имелся начальный новый. Новым значением (word, corpus) будет тогда word + start_newid [corpus].

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

  2. Еще одна вещь, которую вы можете попробовать, это пересмотреть данные.

    Допустим, вы можете держать в памяти только 1,1 из этих монстров. Затем вы можете загрузить один и создать файл dict меньшего размера или массив, который соответствует только первым 10% пар (слово, корпус). Вы можете сканировать загруженный диктовку и иметь дело с любым из тех, которые находятся в первых 10%. Когда вы закончите, вы можете записать результат обратно на диск и сделать еще один проход для вторых 10%. Это потребует 10 проходов, но это может быть хорошо для вас.

    Если вы выбрали свою предыдущую порцию, основываясь на том, что поместилось бы в памяти, вам придется произвольно разбивать ваши старые дикты пополам, чтобы вы могли удерживать один в памяти, сохраняя при этом результирующий диалог / массив.

0 голосов
/ 17 февраля 2010

Как то так, если я правильно понимаю ваш вопрос

from collections import defaultdict
import pickle

result = defaultdict(int)
for fn in filenames:
    data_dict = pickle.load(open(fn))
    for k,count in data_dict.items():
        word,corpus = k
        result[k]+=count
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...