Python: TypeError: unhashable тип: 'list' при запросе MongoDB - PullRequest
0 голосов
/ 15 октября 2018

Чтобы вам было проще понять мою проблему, я приведу краткое изложение ранее.

"Сегодня я просто запрашиваю плоские файлы, к которым у меня никогда не было доступа, но тот же код работает с другими плоскими файлами на том же MongoDBколлекция. "

Ниже детали,

У меня есть список для запроса customer_id, мой список называется alist

[7068, 7116, 7154, 7342, 7379]

Явыполнение запроса MongoDB с использованием pandas и pymongo на python.Вот мой запрос MongoDB. Это библиотека, которую я импортировал

import pandas as pd
from pymongo import MongoClient
import datetime as dt

После этого я даю учетные данные базы данных.Вот учетные данные

mongo_client = MongoClient(host= ... ,port= ... ,username= ...,password= ... ,authSource='admin')
db = mongo_client['something-info']
cv = db['flat_something']

А вот запрос

data = cv.find()
query_filter_alist = {'customer_id': {'$in': alist}}
query_project = {'_id':0}
cursor_list = cv.find(query_filter_alist, query_project)
contacts = pd.DataFrame(list(cursor_list)).drop_duplicates()

Он работает с другими flat_files в той же коллекции MongoDB, но не работает для этих плоских файлов.Вот сообщение об ошибке

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<timed exec> in <module>()

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in drop_duplicates(self, subset, keep, inplace)
   3096         """
   3097         inplace = validate_bool_kwarg(inplace, 'inplace')
-> 3098         duplicated = self.duplicated(subset, keep=keep)
   3099 
   3100         if inplace:

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in duplicated(self, subset, keep)
   3142 
   3143         vals = (self[col].values for col in subset)
-> 3144         labels, shape = map(list, zip(*map(f, vals)))
   3145 
   3146         ids = get_group_index(labels, shape, sort=False, xnull=False)

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in f(vals)
   3131         def f(vals):
   3132             labels, shape = algorithms.factorize(
-> 3133                 vals, size_hint=min(len(self), _SIZE_HINT_LIMIT))
   3134             return labels.astype('i8', copy=False), len(shape)
   3135 

~/anaconda3/lib/python3.6/site-packages/pandas/core/algorithms.py in factorize(values, sort, order, na_sentinel, size_hint)
    558     uniques = vec_klass()
    559     check_nulls = not is_integer_dtype(original)
--> 560     labels = table.get_labels(values, uniques, 0, na_sentinel, check_nulls)
    561 
    562     labels = _ensure_platform_int(labels)

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_labels()

TypeError: unhashable type: 'list'

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

1 Ответ

0 голосов
/ 15 октября 2018

Укажите образец cursor_list и как выглядит contacts, когда нет ошибки или без drop_duplicates().В этом примере ошибка появляется, когда одно из переданных значений представляет собой список ['a', 'b']:

In [2]: pd.DataFrame(pd.Series([['a', 'b'], 'c', ['a', 'b']]))  # ok
Out[2]:
        0
0  [a, b]
1       c
2  [a, b]

In [3]: pd.DataFrame(pd.Series([['a', 'b'], 'c', ['a', 'b']])).drop_duplicates()  # error
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

Все значения списка необходимо преобразовать во что-то hashable , который Python использует для определения уникальности значений для удаления дубликатов.Например, кортеж:

In [5]: df = pd.DataFrame(pd.Series([['a', 'b'], 'c', ['a', 'b']]))  # duplicate

In [6]: df.apply(lambda x: tuple(*x), axis=1)
Out[6]:
0    (a, b)
1      (c,)
2    (a, b)
dtype: object

In [7]: df.apply(lambda x: tuple(*x), axis=1).drop_duplicates()
Out[7]:
0    (a, b)
1      (c,)
dtype: object

Вероятно, вам потребуется выполнить это в два этапа: сначала загрузить, затем применить + drop:

contacts = pd.DataFrame(list(cursor_list))
contacts = contacts.apply(lambda x: tuple(*x), axis=1).drop_duplicates()

И обязательно использовать его на определенныхстолбцы которые нужны, и не все.

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