मोंडोडब से पंडों तक डेटा कैसे आयात करें?


99

मेरे पास मंगोलोड में एक संग्रह में बड़ी मात्रा में डेटा है जिसका मुझे विश्लेषण करने की आवश्यकता है। मैं उस डेटा को पांडा से कैसे आयात करूं?

मैं पांडा और सुन्न के लिए नया हूं।

EDIT: मोंगोडब संग्रह में दिनांक और समय के साथ टैग किए गए सेंसर मान हैं। सेंसर मान फ्लोट डेटाटाइप के होते हैं।

नमूना डेटा:

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

MongoEngine के साथ एक कस्टम फ़ील्ड प्रकार का उपयोग करके पंडों DataFrames को स्टोर करना और पुनः प्राप्त करना सरल हो सकता हैmongo_doc.data_frame = my_pandas_df
Jthorpe

जवाबों:


133

pymongo मैं आपको एक हाथ दे सकता हूं, अनुवर्ती कुछ कोड हैं जो मैं उपयोग कर रहा हूं:

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

धन्यवाद, यह वह विधि है जिसका मैंने उपयोग किया है। मेरे पास प्रत्येक पंक्ति में एम्बेडेड दस्तावेज़ों की एक सरणी भी थी। इसलिए मुझे यह बताना पड़ा कि प्रत्येक पंक्ति के भीतर भी। क्या ऐसा करने के लिए इससे अच्छा तरीका है??
नितिन

क्या आपके मोंगोडब की संरचना के कुछ नमूने प्रदान करना संभव है?
वेटकुओ

3
ध्यान दें सीपीयू को ठंडा रखने के लिए सूची या जनरेटर के रूप में list()अंदर का df = pd.DataFrame(list(cursor))मूल्यांकन। यदि आपके पास एक zillty-one डेटा आइटम है, और अगली कुछ पंक्तियों में यथोचित रूप से विभाजन, स्तर-की-विस्तृत, और उन्हें क्लिप किया जाता है, तो संपूर्ण शर्मिंदगी अभी भी ड्रॉप करने के लिए सुरक्षित है।
Phlip

2
यह बहुत धीमी है @ df = pd.DataFrame(list(cursor))। शुद्ध डीबी क्वैरिंग बहुत तेज है। क्या हम listकास्टिंग को कुछ और में बदल सकते हैं ?
पीटर.क

1
@ उस रेखा ने मेरी आँखों को भी पकड़ लिया। डेटाबेस कर्सर को कास्टिंग करना, जो कि पुनरावृत्त होने के लिए डिज़ाइन किया गया है और संभावित रूप से बड़ी मात्रा में डेटा को लपेटता है, एक इन-मेमोरी सूची में मुझे चतुर नहीं लगता है।
रफा

41

आप इस कोड का उपयोग करके अपने मोंगोडब डेटा को पैंडास डेटाफ़्रेम में लोड कर सकते हैं। इससे मेरा काम बनता है। उम्मीद है आपके लिए भी।

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()))

24

Monaryवास्तव में यही करता है, और यह सुपर फास्ट है । ( एक और कड़ी )

इस शांत पोस्ट को देखें जिसमें एक त्वरित ट्यूटोरियल और कुछ समय शामिल हैं।


क्या Monary स्ट्रिंग डेटा प्रकार का समर्थन करती है?
स्नेहल परमार

मैंने मोनेरी की कोशिश की, लेकिन इसमें काफी समय लग रहा है। क्या मुझे कुछ अनुकूलन याद आ रहा है? रिकॉर्ड्स के client = Monary(host, 27017, database="db_tmp") columns = ["col1", "col2"] data_type = ["int64", "int64"] arrays = client.query("db_tmp", "coll", {}, columns, data_type)लिए प्रयास किया 50000जाता है 200s
निशांत

यह बहुत धीमा लगता है ... सच कहूँ तो, मुझे नहीं पता कि इस परियोजना की स्थिति क्या है, अब, 4 साल बाद ...
shx2

16

पीईपी के अनुसार, सरल जटिल से बेहतर है:

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

आप शर्तों को शामिल कर सकते हैं जैसे आप नियमित mongoDB डेटाबेस के साथ काम करेंगे या यहां तक ​​कि find_one () का उपयोग डेटाबेस से केवल एक तत्व प्राप्त करने के लिए कर सकते हैं, आदि।

और आवाज!


pd.DataFrame.from_records DataFrame (सूची ()) के रूप में धीमा लगता है, लेकिन परिणाम बहुत असंगत हैं। %% समय ने 800 एमएस से 1.9 s तक
AFD

1
यह बहुत बड़े रिकॉर्ड के लिए अच्छा नहीं है क्योंकि यह मेमोरी में त्रुटि नहीं दिखाता है, इंस्ट्रेड बहुत बड़े डेटा के लिए सिस्टम को हैंग करता है। जबकि pd.DataFrame (सूची (कर्सर)) मेमोरी एरर दिखाता है।
अमूल्य आचार्य

13
import pandas as pd
from odo import odo

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

9

कुशलता के साथ आउट-ऑफ-कोर (रैम में फिटिंग नहीं) डेटा (यानी समानांतर निष्पादन के साथ) के लिए, आप पायथन ब्लेज़ इकोसिस्टम की कोशिश कर सकते हैं : ब्लेज़ / मास्क / ओडो की ।

ब्लेज़ (और ओडो)MongoDB से निपटने के लिए ) के पास आउट-ऑफ-द-बॉक्स फ़ंक्शन हैं।

शुरू करने के लिए कुछ उपयोगी लेख:

और एक लेख जो दिखाता है कि ब्लेज़ स्टैक के साथ कौन सी अद्भुत चीजें संभव हैं: विश्लेषण 1.7 बिलियन रेडिट टिप्पणियाँ ब्लेज़ और इम्पाला के साथ (आवश्यक रूप से, सेकंड में 975 जीबी की रेडिट टिप्पणियों को क्वेरी करना)।

PS मैं इनमें से किसी भी तकनीक से संबद्ध नहीं हूं।


1
मैंने एक उदाहरण के साथ Jupyter नोटबुक का उपयोग करके एक पोस्ट भी लिखी है कि कैसे Dask एक मशीन पर कई कोर का उपयोग करके मेमोरी में डेटा फिटिंग पर भी निष्पादन में तेजी लाने में मदद करता है।
डेनिस गोलोमेज़ोव

8

एक अन्य विकल्प जो मुझे बहुत उपयोगी लगा वह है:

from pandas.io.json import json_normalize

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

इस तरह आपको मुफ्त में नेस्टेड मोंगोडब दस्तावेजों की अनफॉलोइंग मिल जाती है।


2
मुझे इस पद्धति से एक त्रुटि मिलीTypeError: data argument can't be an iterator
गेब्रियल फेयर

2
अजीब बात है, यह 3.6.7पांडा का उपयोग करके मेरे अजगर पर काम करता है 0.24.2। शायद आप df = json_normalize(list(cursor))इसके बजाय कोशिश कर सकते हैं ?
इकर पोहोरस्की

+1 के लिए। डॉक्स, max_level तर्क अधिकतम गहराई के अधिकतम स्तर को परिभाषित करता है। मैंने सिर्फ एक परीक्षण किया और यह सच नहीं है, इसलिए कुछ स्तंभों को। फिर भी, मैंगोडब के साथ काम करने के लिए बहुत अच्छी सुविधा।
मौरिसियो मारुतो

5

का उपयोग करते हुए

pandas.DataFrame(list(...))

यदि मेमोरी / जनरेटर का परिणाम बड़ा है, तो बहुत सारी मेमोरी का उपभोग करेगा

अंत में छोटे विखंडू और अवतल उत्पन्न करने के लिए बेहतर है

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)


1

Waitkuo द्वारा इस महान जवाब के बाद मैं ऐसा करने की संभावना जोड़ना चाहूंगा कि .Cl_sql () और .read_csv () के साथ लाइन में chunksize का उपयोग करना । मैं 'इटेरेटर' / 'कर्सर' के एक-एक 'रिकॉर्ड' के द्वारा जाने से बचते हुए डेउंग से उत्तर को बढ़ाता हूँ । मैं पिछले 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

राफेल वलेरो, waitingkuo और Deu लीयुंग की तरह एक समान दृष्टिकोण का उपयोग कर पृष्ठांकन :

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

0

आप तीन लाइनों में pdmongo के साथ जो चाहें प्राप्त कर सकते हैं:

import pdmongo as pdm
import pandas as pd
df = pdm.read_mongo("MyCollection", [], "mongodb://localhost:27017/mydb")

यदि आपका डेटा बहुत बड़ा है, तो आप जो डेटा नहीं चाहते हैं, उसे फ़िल्टर करके पहले एक समग्र क्वेरी कर सकते हैं, फिर उन्हें अपने इच्छित कॉलम में मैप कर सकते हैं।

Readings.aकॉलम aद्वारा मैपिंग और फ़िल्टरिंग का एक उदाहरण यहां दिया गया है reportCount:

import pdmongo as pdm
import pandas as pd
df = pdm.read_mongo("MyCollection", [{'$match': {'reportCount': {'$gt': 6}}}, {'$unwind': '$Readings'}, {'$project': {'a': '$Readings.a'}}], "mongodb://localhost:27017/mydb")

read_mongoपाइमोन्गो एग्रीगेट के समान तर्क स्वीकार करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.