python mongodb pandas pymongo

python - ¿Cómo importar datos de mongodb a los pandas?



pymongo (11)

Tengo una gran cantidad de datos en una colección en mongodb que necesito analizar. ¿Cómo importo esa información a los pandas?

Soy nuevo para pandas y numpy.

EDITAR: La colección de mongodb contiene valores de sensor etiquetados con fecha y hora. Los valores del sensor son de tipo de datos flotantes.

Data de muestra:

{ "_cls" : "SensorReport", "_id" : ObjectId("515a963b78f6a035d9fa531b"), "_types" : [ "SensorReport" ], "Readings" : [ { "a" : 0.958069536790466, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:26:35.297Z"), "b" : 6.296118156595, "_cls" : "Reading" }, { "a" : 0.95574014778624, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:27:09.963Z"), "b" : 6.29651468650064, "_cls" : "Reading" }, { "a" : 0.953648289182713, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:27:37.545Z"), "b" : 7.29679823731148, "_cls" : "Reading" }, { "a" : 0.955931884300997, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:28:21.369Z"), "b" : 6.29642922525632, "_cls" : "Reading" }, { "a" : 0.95821381, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:41:20.801Z"), "b" : 7.28956613, "_cls" : "Reading" }, { "a" : 4.95821335, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:41:36.931Z"), "b" : 6.28956574, "_cls" : "Reading" }, { "a" : 9.95821341, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:42:09.971Z"), "b" : 0.28956488, "_cls" : "Reading" }, { "a" : 1.95667927, "_types" : [ "Reading" ], "ReadingUpdatedDate" : ISODate("2013-04-02T08:43:55.463Z"), "b" : 0.29115237, "_cls" : "Reading" } ], "latestReportTime" : ISODate("2013-04-02T08:43:55.463Z"), "sensorName" : "56847890-0", "reportCount" : 8 }


Después de esta gran respuesta de waitingkuo me gustaría agregar la posibilidad de hacerlo utilizando chunksize en línea con .read_sql() y .read_csv() . Amplié la respuesta de Deu Leung evitando ir uno a uno cada ''registro'' del ''iterador'' / ''cursor''. Pediré prestada la función read_mongo anterior.

def read_mongo(db, collection, query={}, host=''localhost'', port=27017, username=None, password=None, chunksize = 100, no_id=True): """ Read from Mongo and Store into DataFrame """ # Connect to MongoDB #db = _connect_mongo(host=host, port=port, username=username, password=password, db=db) client = MongoClient(host=host, port=port) # Make a query to the specific DB and Collection db_aux = client[db] # Some variables to create the chunks skips_variable = range(0, db_aux[collection].find(query).count(), int(chunksize)) if len(skips_variable)<=1: skips_variable = [0,len(skips_variable)] # Iteration to create the dataframe in chunks. for i in range(1,len(skips_variable)): # Expand the cursor and construct the DataFrame #df_aux =pd.DataFrame(list(cursor_aux[skips_variable[i-1]:skips_variable[i]])) df_aux =pd.DataFrame(list(db_aux[collection].find(query)[skips_variable[i-1]:skips_variable[i]])) if no_id: del df_aux[''_id''] # Concatenate the chunks into a unique df if ''df'' not in locals(): df = df_aux else: df = pd.concat([df, df_aux], ignore_index=True) return df


Otra opción que encontré muy útil es:

from pandas.io.json import json_normalize cursor = my_collection.find() df = json_normalize(cursor)

De esta forma, obtienes el despliegue de documentos mongodb anidados de forma gratuita.


Para tratar con datos fuera del núcleo (que no se ajustan a la RAM) de manera eficiente (es decir, con ejecución paralela), puede probar el ecosistema Python Blaze : Blaze / Dask / Odo.

Blaze (y Odo ) tiene funciones listas para usar para manejar MongoDB.

Algunos artículos útiles para comenzar:

Y un artículo que muestra qué cosas increíbles son posibles con Blaze stack: analizando 1.7 mil millones de comentarios de Reddit con Blaze e Impala (en esencia, consultar 975 Gb de comentarios de Reddit en segundos).

PD: No estoy afiliado a ninguna de estas tecnologías.


Puede cargar sus datos de mongodb en pandas DataFrame utilizando este código. Esto funciona para mi. Afortunadamente para ti también

import pymongo import pandas as pd from pymongo import MongoClient client = MongoClient() db = client.database_name collection = db.collection_name data = pd.DataFrame(list(collection.find()))


Según PEP, simple es mejor que complicado:

import pandas as pd df = pd.DataFrame.from_records(db.<database_name>.<collection_name>.find())

Puede incluir condiciones tal como lo haría con la base de datos mongoDB normal o incluso usar find_one () para obtener solo un elemento de la base de datos, etc.

¡y voilá!


Un enfoque similar al de Rafael Valero, waitingkuo y Deu Leung usando la paginación :

def read_mongo( # db, collection, query=None, # host=''localhost'', port=27017, username=None, password=None, chunksize = 100, page_num=1, no_id=True): # Connect to MongoDB db = _connect_mongo(host=host, port=port, username=username, password=password, db=db) # Calculate number of documents to skip skips = chunksize * (page_num - 1) # Sorry, this is in spanish # https://www.toptal.com/python/c%C3%B3digo-buggy-python-los-10-errores-m%C3%A1s-comunes-que-cometen-los-desarrolladores-python/es if not query: query = {} # Make a query to the specific DB and Collection cursor = db[collection].find(query).skip(skips).limit(chunksize) # Expand the cursor and construct the DataFrame df = pd.DataFrame(list(cursor)) # Delete the _id if no_id: del df[''_id''] return df


Utilizando

pandas.DataFrame(list(...))

consumirá mucha memoria si el resultado del iterador / generador es grande

mejor generar pequeños trozos y concat al final

def iterator2dataframes(iterator, chunk_size: int): """Turn an iterator into multiple small pandas.DataFrame This is a balance between memory and efficiency """ records = [] frames = [] for i, record in enumerate(iterator): records.append(record) if i % chunk_size == chunk_size - 1: frames.append(pd.DataFrame(records)) records = [] if records: frames.append(pd.DataFrame(records)) return pd.concat(frames)




pymongo podría darte una mano, los siguientes son algunos códigos que estoy usando:

import pandas as pd from pymongo import MongoClient def _connect_mongo(host, port, username, password, db): """ A util for making a connection to mongo """ if username and password: mongo_uri = ''mongodb://%s:%s@%s:%s/%s'' % (username, password, host, port, db) conn = MongoClient(mongo_uri) else: conn = MongoClient(host, port) return conn[db] def read_mongo(db, collection, query={}, host=''localhost'', port=27017, username=None, password=None, no_id=True): """ Read from Mongo and Store into DataFrame """ # Connect to MongoDB db = _connect_mongo(host=host, port=port, username=username, password=password, db=db) # Make a query to the specific DB and Collection cursor = db[collection].find(query) # Expand the cursor and construct the DataFrame df = pd.DataFrame(list(cursor)) # Delete the _id if no_id: del df[''_id''] return df


import pandas as pd from odo import odo data = odo(''mongodb://localhost/db::collection'', pd.DataFrame)