PyMongo
を使用してmongodbにpandas DataFrameを挿入する最も簡単な方法は何ですか?
試行
_db.myCollection.insert(df.to_dict())
_
エラーを与えた
InvalidDocument: documents must have only string keys, the key was Timestamp('2013-11-23 13:31:00', tz=None)
_db.myCollection.insert(df.to_json())
_
エラーを与えた
_
TypeError: 'str' object does not support item assignment
__db.myCollection.insert({id: df.to_json()})
_
エラーを与えた
_InvalidDocument: documents must have only string a keys, key was <built-in function id>
_
df
_<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 150 entries, 2013-11-23 13:31:26 to 2013-11-23 13:24:07
Data columns (total 3 columns):
amount 150 non-null values
price 150 non-null values
tid 150 non-null values
dtypes: float64(2), int64(1)
_
私はquickestとsimpleメソッドの両方があるとは思わない。データ変換の心配がなければ、次のことができます
>>> import json
>>> df = pd.DataFrame.from_dict({'A': {1: datetime.datetime.now()}})
>>> df
A
1 2013-11-23 21:14:34.118531
>>> records = json.loads(df.T.to_json()).values()
>>> db.myCollection.insert(records)
ただし、 データをロードバック しようとすると、次のようになります:
>>> df = read_mongo(db, 'myCollection')
>>> df
A
0 1385241274118531000
>>> df.dtypes
A int64
dtype: object
したがって、datetime
内のint
、float
、またはstr
フィールド以外のすべてと同様に、 'A'列をDataFrame
sに戻す必要があります。この例では:
>>> df['A'] = pd.to_datetime(df['A'])
>>> df
A
0 2013-11-23 21:14:34.118531
ここには、最も速い方法があります。 insert_many
pymongo 3のメソッドと to_dict
メソッド。
db.insert_many(df.to_dict('records'))
odo を使用して実行できます
odo(df, db.myCollection)
データフレームにデータがない(つまりNone、nan)があり、ドキュメントにNULLキー値が必要ない場合:
db.insert_many(df.to_dict("records"))
は、null値を持つキーを挿入します。ドキュメントに空のキー値が必要ない場合は、以下のコードのpandas .to_dict("records")
)の修正バージョンを使用できます。
from pandas.core.common import _maybe_box_datetimelike
my_list = [dict((k, _maybe_box_datetimelike(v)) for k, v in Zip(df.columns, row) if v != None and v == v) for row in df.values]
db.insert_many(my_list)
どこ if v != None and v == v
値をNone
またはnan
でないことを確認して、行の辞書に入れる前にチェックを追加しました。 .insert_many
には、ドキュメント内の値を持つキーのみが含まれます(null
データ型は含まれません)。
この質問には素晴らしいアイデアがあると思います。私の場合、大規模なデータフレームの移動にもっと注意を払っています。これらの場合pandasは、chunksizeのオプションを許可する傾向があります(たとえば、 pandas。 DataFrame.to_sql )。だから私はこの方向で使用している関数を追加することでここに貢献すると思います。
def write_df_to_mongoDB( my_df,\
database_name = 'mydatabasename' ,\
collection_name = 'mycollectionname',
server = 'localhost',\
mongodb_port = 27017,\
chunk_size = 100):
#"""
#This function take a list and create a collection in MongoDB (you should
#provide the database name, collection, port to connect to the remoete database,
#server of the remote database, local port to tunnel to the other machine)
#
#---------------------------------------------------------------------------
#Parameters / Input
# my_list: the list to send to MongoDB
# database_name: database name
#
# collection_name: collection name (to create)
# server: the server of where the MongoDB database is hosted
# Example: server = '132.434.63.86'
# this_machine_port: local machine port.
# For example: this_machine_port = '27017'
# remote_port: the port where the database is operating
# For example: remote_port = '27017'
# chunk_size: The number of items of the list that will be send at the
# some time to the database. Default is 100.
#
#Output
# When finished will print "Done"
#----------------------------------------------------------------------------
#FUTURE modifications.
#1. Write to SQL
#2. Write to csv
#----------------------------------------------------------------------------
#30/11/2017: Rafael Valero-Fernandez. Documentation
#"""
#To connect
# import os
# import pandas as pd
# import pymongo
# from pymongo import MongoClient
client = MongoClient('localhost',int(mongodb_port))
db = client[database_name]
collection = db[collection_name]
# To write
collection.delete_many({}) # Destroy the collection
#aux_df=aux_df.drop_duplicates(subset=None, keep='last') # To avoid repetitions
my_list = my_df.to_dict('records')
l = len(my_list)
ran = range(l)
steps=ran[chunk_size::chunk_size]
steps.extend([l])
# Inser chunks of the dataframe
i = 0
for j in steps:
print j
collection.insert_many(my_list[i:j]) # fill de collection
i = j
print('Done')
return
文字列キーを作成するだけです!
import json
dfData = json.dumps(df.to_dict('records'))
savaData = {'_id': 'a8e42ed79f9dae1cefe8781760231ec0', 'df': dfData}
res = client.insert_one(savaData)
##### load dfData
data = client.find_one({'_id': 'a8e42ed79f9dae1cefe8781760231ec0'}).get('df')
dfData = json.loads(data)
df = pd.DataFrame.from_dict(dfData)
これはどう:
db.myCollection.insert({id: df.to_json()})
idはそのdfの一意の文字列になります