web-dev-qa-db-fra.com

Comment importer des données de mongodb vers des pandas?

J'ai une grande quantité de données dans une collection de mongodb que je dois analyser. Comment puis-je importer ces données sur des pandas?

Je suis nouveau sur pandas et numpy.

EDIT: La collection mongodb contient des valeurs de capteur étiquetées avec la date et l'heure. Les valeurs du capteur sont du type de données float.

Exemple de données:

{
"_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
}
78
Nithin

pymongo pourrait vous donner un coup de main, voici quelques codes que j'utilise:

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
104
waitingkuo

Vous pouvez charger vos données mongodb sur pandas DataFrame en utilisant ce code. Cela fonctionne pour moi. J'espère pour vous aussi.

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()))
30
saimadhu.polamuri

Monary fait exactement cela, et c'est très rapide . ( n autre lien )

Voir ce post cool qui comprend un tutoriel rapide et quelques timings.

22
shx2

Selon PEP, simple vaut mieux que compliqué:

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

Vous pouvez inclure des conditions comme vous le feriez avec une base de données mongoDB classique ou même utiliser find_one () pour obtenir un seul élément de la base de données, etc.

et le tour est joué!

11
Cy Bu
import pandas as pd
from odo import odo

data = odo('mongodb://localhost/db::collection', pd.DataFrame)
10
fengwt

Pour gérer efficacement les données hors cœur (ne s'intégrant pas dans la RAM) (c'est-à-dire avec une exécution en parallèle), vous pouvez essayer écosystème Python Blaze : Blaze/Dask/Odo.

Blaze (et Odo ) possède des fonctions prédéfinies pour gérer MongoDB.

Quelques articles utiles pour commencer:

Et un article qui montre les possibilités incroyables de Blaze stack: Analyse de 1,7 milliard de commentaires Reddit avec Blaze et Impala (essentiellement, interroger 975 Go de commentaires Reddit en quelques secondes).

P.S. Je ne suis affilié à aucune de ces technologies.

6
Dennis Golomazov

Une autre option que j'ai trouvée très utile est:

from pandas.io.json import json_normalize

cursor = my_collection.find()
df = json_normalize(cursor)

de cette façon, vous obtenez gratuitement le déploiement des documents imbriqués mongodb.

4
Ikar Pohorský

En utilisant

pandas.DataFrame(list(...))

consomme beaucoup de mémoire si le résultat de l'itérateur/générateur est volumineux

mieux générer de petits morceaux et concat à la fin

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)
3
Deo Leung

http://docs.mongodb.org/manual/reference/mongoexport

exporter en csv et utiliser read_csv ou JSON et utilisez DataFrame.from_records

2
Jeff

Suite à cette excellente réponse de waitingkuo , je voudrais ajouter la possibilité de le faire en utilisant chunksize en ligne avec . Read_sql () et . Read_csv () =. J'élargis la réponse de Deu Leung en évitant d'aller un à un chaque "enregistrement" de "l'itérateur"/"curseur". Je vais emprunter la fonction précédente read_mongo .

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
1
Rafael Valero

Une approche similaire à celle de Rafael Valero, waitingkuo et Deu Leung utilisant pagination:

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
1
Jordy Cuan