深入比拟数据科学东西箱:Python和R 非布局化数据的布局化
概述在现实场景中,由于数据来历的异构,数据源的名目往往是难以统一的,这就导致大量具有代价的数据凡是是以非布局化的形式聚合在一起的。对付这些非布局化数据,最常见的数据布局就是JSON,而对应的数据库就是MongoDB。
操作MongoDB这样的NoSQL数据库,我们可以把异构的数据源整合到若干个collection中,通过key-value的形式对数据举办增删改查。固然MongoDB在数据聚合上有天然的优势,可是在事务处理惩罚(OLTP)与数据阐明(OLAP)上的表示却不尽人意。由于MongoDB自身是一个文档型数据库,一方面,MongoDB 并没有事务的观念,所以在需要担保数据一致性的场景下并欠好用。另一方面,MongoDB的join查询也没有RDBMS来得直观利便,所以在需要多表关联查询的场景下也很是捉急。
凡是,对付小数据集,我们城市将数据导入到雷同MySQL这样的RDBMS中做进一步的布局化处理惩罚,对付大数据集则可以通过Hive导入到HDFS上。那么,将MongoDB的非布局化数据导入到RDBMS中的最优方案又是什么呢?本文将对非布局化数据与布局化数据的管道构建做具体的接头。
从 Mongo 到 MySQL
iPython从Mongo迁移数据到MySQL,我的第一个回响是应该写个剧本,我首先想到了用Python从Mongo读取数据到内存中然后再批量写入MySQL。
这里,我选择了利用pymongo。%% bashpip install pymongo# 这里不需要安装 Mongo的client首先是读取Mongo数据from pymongo import MongoClientclient = MongoClient(‘192.168.1.100’, 27017)db = client[‘tesedb’]posts = db.test_collectioncondition = {‘_id’:’harryzhu’}result_set = posts.find(condition)for i in result_set: print(i)这里由于python会有中文的问题,我本身界说了一个将unicode转为utf-8的函数:def getMongoData(data,field): if data[field] is None: return(“”) else: if isinstance(data[field], unicode): return(data[field].encode(“utf-8”)) else: return(data[field])接着,筹备往MySQL中导入数据%% bashpip install MySQL-python# 这里需要安装 MySQL的clientimport MySQLdbdb = MySQLdb.connect(“192.168.1.100″,”root”,”harryzhu”,”testdb” )cursor = db.cursor()
values = r”(\'{id}\’,\'{value}\’,\'{datetime}\’,\'{stock_code}\’,\'{share}\’)”.format(id=getMongoData(i,”_id”),value=getMongoData(i,”value”),datetime=getMongoData(i,”datetime”),stock_code=getMongoData(i,”stock_code”),share=getMongoData(i,”share”))
sql = r”INSERT INTO `FinanceR` (`id`,`value`,`datetime`,`stock_code`,`share`) VALUES ” + values
try: cursor.execute(sql) db.commit()except: db.rollback()
db.close()从Mongo中读取的JSON需要在这里拼接SQL语句是一件用户体验很是糟糕的工作,假如有更好的要领接待在留言区接头。在实验拼接sql 2个小时后,我坚决放弃了用Python导数据的想法。
R由于拼接SQL长短常蛋疼的一件工作,我想到了操作R中的data frame直接完成数据的插入黑邪术。
首先,同样是需要将数据从Mongo中读取出来.在实验利用RMongo,rmongodb以及mongolite之后,我依然选择了较量陈腐的RMongo。在利用的进程中,这三个包都有各自的问题。
rmongodb的教程暗昧不清,看了好久都没有找到挪用长途mongo数据库的case,而出于jeroenooms大人之手的后起之秀mongolite则在导入数据的时候坚决的丢失了很是要害的_id字段,在安装包之后会呈现jsonlite依赖包的异常。RMongo则在读取数据时将两其中文字段夹杂成了一个字段,导致整个数据布局错杂。
三条路子全军淹没,这让我情何故堪,亏得利用R的履历颇丰,通过中文的转换和切割就轻松办理了这个问题。
下面演示一下如何利用RMongo办理Mongo数据的读取:
install.packages(“RMongo”)Sys.setenv(“Java_HOME”=”/usr/bin/java”)library(RMongo)# 这里不需要安装 Mongo的clientlibrary(dplyr)# 配置数据库FinanceR <- RMongo::mongoDbConnect(host=”192.168.1.100″)dbShowCollections(FinanceR)
# 配置查询语句condition = “{}”# 获得返回功效output <- RMongo::dbGetQuery(FinanceR, collection=”portfolio_20160619”, condition, skip=0, limit=2)
input <- output %>% dplyr::mutate(stock_name1 = iconv(strsplit(iconv(stock_name,from = “utf-8”, to = “gbk”),”\100″)[[1]][1],from = “gbk”,to = “utf-8”))%>% dplyr::mutate(portfolio_name = iconv(strsplit(iconv(stock_name,from = “utf-8”, to = “gbk”),”\100″)[[1]][2],from = “gbk”,to = “utf-8″))%>% dplyr::select(-stock_name)%>% rbind(cum_value=””,risk=””)
dbDisconnect(FinanceR)此刻,我们已经把Mongo中的数据乐成导入到了内存中,下面将讲授如何利用黑邪术直接将整个data frame压入数据库。install.packages(“RMySQL”)library(RMySQL)# 这里不需要安装 MySQL的client
con <- RMySQL::dbConnect(RMySQL::MySQL(), user=”FinanceR”, password=”FinanceR”, dbname=”FinanceR”, host=”192.168.1.100″)
# 选择追加,而不是重写的方法来添加数据,不然数据库的schema会被重写 RMySQL::dbWriteTable(con,input,row.names = FASLE, overwrite = FALSE, append = TRUE)on.exit(dbDisconnect(con))
ShellPython 和 R 的方法各有利弊,对付Python而言今朝简朴粗暴的方法就是SQL拼接,而R则在流水化上较量坚苦。所以最后转向寻求Shell呼吁的方法,通过挪用 Mongo client 和 MySQL client 的 API 来完成整个数据的转化操纵。
颠末研究发明 Mongo Client 提供了将数据转成 csv 名目标接口,之后mysql则通过load呼吁可以将数据加载到数据库中。
结论通过将非布局化数据转化为 data frame 后直接压入 RDBMS,一方面省去了枯燥的SQL拼接,一方面操纵又直观清晰不易堕落,对付小数据荟萃,直接用这样的要领增量导入数据不失为一种好要领,对付批量数据的流水化则回收Shell剧本挪用Mongo和MySQL客户端呼吁较为符合。
参考资料Python MySQL Database AccessR client to interface with MongoDBpython+mongoDB+pymongo常见呼吁及简朴案例
接待插手本站果真乐趣群贸易智能与数据阐明群乐趣范畴包罗各类让数据发生代价的步伐,实际应用案例分享与接头,阐明东西,ETL东西,数据客栈,数据挖掘东西,报表系统等全方位常识QQ群:81035754