在Python中利用Into包整洁地进行数据迁移的教程


Posted in Python onMarch 30, 2015

动机

我们花费大量的时间将数据从普通的交换格式(比如CSV),迁移到像数组、数据库或者二进制存储等高效的计算格式。更糟糕的是,许多人没有将数据迁移到高效的格式,因为他们不知道怎么(或者不能)为他们的工具管理特定的迁移方法。

你所选择的数据格式很重要,它会强烈地影响程序性能(经验规律表明会有10倍的差距),以及那些轻易使用和理解你数据的人。

当提倡Blaze项目时,我经常说:“Blaze能帮助你查询各种格式的数据。”这实际上是假设你能够将数据转换成指定的格式。

进入into项目

into函数能在各种数据格式之间高效的迁移数据。这里的数据格式既包括内存中的数据结构,比如:

列表、集合、元组、迭代器、numpy中的ndarray、pandas中的DataFrame、dynd中的array,以及上述各类的流式序列。

也包括存在于Python程序之外的持久化数据,比如:

CSV、JSON、行定界的JSON,以及以上各类的远程版本

HDF5 (标准格式与Pandas格式皆可)、 BColz、 SAS、 SQL 数据库 ( SQLAlchemy支持的皆可)、 Mongo

into项目能在上述数据格式的任意两个格式之间高效的迁移数据,其原理是利用一个成对转换的网络(该文章底部有直观的解释)。

如何使用它

into函数有两个参数:source和target。它将数据从source转换成target。source和target能够使用如下的格式:

Target     Source     Example

Object    Object      A particular DataFrame or list

String     String      ‘file.csv', ‘postgresql://hostname::tablename'

Type                   Like list or pd.DataFrame

所以,下边是对into函数的合法调用:
 

>>> into(list, df) # create new list from Pandas DataFrame
 
>>> into([], df) # append onto existing list
 
>>> into('myfile.json', df) # Dump dataframe to line-delimited JSON
 
>>> into(Iterator, 'myfiles.*.csv') # Stream through many CSV files
 
>>> into('postgresql://hostname::tablename', df) # Migrate dataframe to Postgres
 
>>> into('postgresql://hostname::tablename', 'myfile.*.csv') # Load CSVs to Postgres
 
>>> into('myfile.json', 'postgresql://hostname::tablename') # Dump Postgres to JSON
 
>>> into(pd.DataFrame, 'mongodb://hostname/db::collection') # Dump Mongo to DataFrame

Note that into is a single function. We're used to doing this with various to_csv, from_sql methods on various types. The into api is very small; Here is what you need in order to get started:

注意,into函数是一个单一的函数。虽然我们习惯于在各种类型上使用to_csv, from_sql等方法来完成这样的功能,但接口into非常简单。开始使用into函数前,你需要:
 

$ pip install into
 
>>> from into import into

在Github上查看into工程。

实例

现在我们展示一些更深层次的相同的实例。

将Python中的list类型转换成numpy中的array类型
 

>>> import numpy as np
 
>>> into(np.ndarray, [1, 2, 3])
 
array([1, 2, 3])

加载CSV文件,并转换成Python中的list类型
 

>>> into(list, 'accounts.csv')
 
[(1, 'Alice', 100),
 
(2, 'Bob', 200),
 
(3, 'Charlie', 300),
 
(4, 'Denis', 400),
 
(5, 'Edith', 500)]

将CSV文件转换成JSON格式
 

>>> into('accounts.json', 'accounts.csv')
 
$ head accounts.json
 
{"balance": 100, "id": 1, "name": "Alice"}
 
{"balance": 200, "id": 2, "name": "Bob"}
 
{"balance": 300, "id": 3, "name": "Charlie"}
 
{"balance": 400, "id": 4, "name": "Denis"}
 
{"balance": 500, "id": 5, "name": "Edith"}

将行定界的JSON格式转换成Pandas中的DataFrame格式
 

>>> import pandas as pd
 
>>> into(pd.DataFrame, 'accounts.json')
 
balance id name
 
0 100 1 Alice
 
1 200 2 Bob
 
2 300 3 Charlie
 
3 400 4 Denis
 
4 500 5 Edith

 它是如何工作的?

格式转换是有挑战性的。任意两个数据格式之间的健壮、高效的格式转换,都充满了特殊情况和奇怪的库。常见的解决方案是通过一个通用格式,例如DataFrame或流内存列表、字典等,进行格式转换。(见dat)或者通过序列化格式,例如ProtoBuf或Thrift,进行格式转换。这些都是很好的选择,往往也是你想要的。然而有时候这样的转换是比较慢的,特别是当你在实时计算系统上转换,或面对苛刻的存储解决方案时。

在Python中利用Into包整洁地进行数据迁移的教程

考虑一个例子,在numpy.recarray和pandas.DataFrame之间进行数据迁移。我们可以非常快速地,适当地迁移这些数据。数据的字节不需要更改,只更改其周围的元数据即可。我们不需要将数据序列化到一个交换格式,或转换为中间的纯Python对象。

考虑从CSV文件迁移数据到一个PostgreSQL数据库。通过SQLAlchemy(注:一个Python环境下的数据库工具箱)使用Python迭代器,我们的迁移速度不太可能超过每秒2000条记录。然而使用PostgreSQL自带的CSV加载器,我们的迁移速度可以超过每秒50000条记录。花费一整晚的时间和花费一杯咖啡的时间进行数据迁移,是有很大区别的。然而这需要我们在特殊情况下,能足够灵活的使用特殊代码。

专门的两两互换工具往往比通用解决方案快一个数量级。

Into项目是那些成对地数据迁移组成的一个网络。我们利用下图展示这个网络:

在Python中利用Into包整洁地进行数据迁移的教程

每个节点是一种数据格式。每个定向的边是一个在两种数据格式之间转换数据的函数。into函数的一个调用,可能会遍历多个边和多个中间格式。例如,当我们将CSV文件迁移到Mongo数据库时,我们可以采取以下路径:

?将CSV文件加载到DataFrame中(利用pandas.read_csv)

?然后转换为np.recarray(利用DataFrame.to_records)

?接着转换为一个Python的迭代器类型(利用np.ndarray.tolist)

?最终转换成Mongo中的数据(利用pymongo.Collection.insert)

或者我们可以使用MongoDB自带的CSV加载器,编写一个特殊函数,用一个从CSV到Mongo的定向边缩短整个处理过程。

为了找到最有效的路线,我们利用相对成本(引入权重的ad-hoc)给这个网络的所有边赋予权重值。然后我们使用networkx找到最短路径,进而进行数据迁移。如果某个边由于某种原因失败了(引发NotImplementedError),我们可以自动重新寻找路径。这样我们的迁移方法是既高效又健壮的。

注意,我们给某些节点涂上红色。这些节点的数据量可以大于内存。当我们在两个红色节点之间进行数据迁移时(输入和输出的数据量都可能大于内存),我们限制我们的路径始终在红色子图中,以确保迁移路径中间的数据不会溢出。需要注意的一种格式是chunks(…),例如chunks(DataFrame)是一个可迭代的,在内存中的DataFrames。这个方便的元格式允许我们在大数据上使用紧凑的数据结构,例如numpy的arrays和pandas的DataFrames,同时保持在内存中数据的只有几十兆字节。

这种网络化的方法允许开发者对于特殊情况编写专门的代码,同时确信这段代码只在正确的情况下使用。这种方法允许我们利用一个独立的、可分离的方式处理一个非常复杂的问题。中央调度系统让我们保持头脑清醒。

历史

很久以前,我写过into链接到Blaze的文章,然后我立即就沉默了。这是因为旧的实现方法(网络方法之前)很难扩展或维护,也没有准备好进入其黄金期。

我很满意这个网络。意想不到的应用程序经常能够正常运行,into工程现在也准备好进入其黄金期了。Into工程可以通过conda和pip得到,而独立于Blaze。它主要的依赖为NumPy、Pandas和NetworkX,所以对于阅读我博客的大部分人来说,它算是相对轻量级的。如果你想利用一些性能更好的格式,例如HDF5,你将同样需要安装这些库(pro-tip,使用conda安装)。

如何开始使用into函数

你应该下载一个最近版本的into工程。
 

$ pip install --upgrade git+https://github.com/ContinuumIO/into
 
or
 
$ conda install into --channel blaze

然后你可能想要通过该教程的上半部分,或者阅读该文档。

又或者不阅读任何东西,只是试一试。我的希望是,这个接口很简单(只有一个函数!),用户可以自然地使用它。如果你运行中出现了问题,那么我很愿意在blaze-dev@continuum.io中听到它们。

Python 相关文章推荐
Python设计模式之观察者模式实例
Apr 26 Python
浅谈python多线程和队列管理shell程序
Aug 04 Python
python3制作捧腹网段子页爬虫
Feb 12 Python
在cmd命令行里进入和退出Python程序的方法
May 12 Python
解决pycharm界面不能显示中文的问题
May 23 Python
通过pycharm使用git的步骤(图文详解)
Jun 13 Python
python实现屏保程序(适用于背单词)
Jul 30 Python
Django中的cookie和session
Aug 27 Python
django中related_name的用法说明
May 20 Python
Python2手动安装更新pip过程实例解析
Jul 16 Python
地图可视化神器kepler.gl python接口的使用方法
Dec 22 Python
Python中X[:,0]和X[:,1]的用法
May 10 Python
在Linux上安装Python的Flask框架和创建第一个app实例的教程
Mar 30 #Python
使用Python中PDB模块中的命令来调试Python代码的教程
Mar 30 #Python
深入讨论Python函数的参数的默认值所引发的问题的原因
Mar 30 #Python
使用Python标准库中的wave模块绘制乐谱的简单教程
Mar 30 #Python
Python中使用语句导入模块或包的机制研究
Mar 30 #Python
优化Python代码使其加快作用域内的查找
Mar 30 #Python
Python中分数的相关使用教程
Mar 30 #Python
You might like
关于手调机和数调机的选择
2021/03/02 无线电
php绘制一个扇形的方法
2015/01/24 PHP
PHP 前加at符合@的作用解析
2015/07/31 PHP
JS嵌套函数调用上下文的问题解决
2014/03/26 Javascript
AngularJS HTML编译器介绍
2014/12/06 Javascript
node.js中的fs.existsSync方法使用说明
2014/12/17 Javascript
jQuery中remove()方法用法实例
2014/12/25 Javascript
jquery果冻抖动效果实现方法
2015/01/15 Javascript
Javascript函数式编程简单介绍
2015/10/11 Javascript
判断数组是否包含某个元素的js函数实现方法
2016/05/19 Javascript
很棒的Bootstrap选项卡切换效果
2016/07/01 Javascript
NodeJs使用Mysql模块实现事务处理实例
2017/05/31 NodeJs
vue实现pdf导出解决生成canvas模糊等问题(推荐)
2018/10/18 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
2019/01/04 Javascript
微信小程序开发常见问题及解决方案
2019/07/11 Javascript
解决$store.getters调用不执行的问题
2019/11/08 Javascript
JQuery省市联动效果实现过程详解
2020/05/08 jQuery
利用JavaScript模拟京东按键输入功能
2020/12/01 Javascript
Python作用域用法实例详解
2016/03/15 Python
Python单体模式的几种常见实现方法详解
2017/07/28 Python
python学生管理系统
2019/01/30 Python
搞定这套Python爬虫面试题(面试会so easy)
2019/04/03 Python
django之使用celery-把耗时程序放到celery里面执行的方法
2019/07/12 Python
使用Filter过滤python中的日志输出的实现方法
2019/07/17 Python
python集合能干吗
2020/07/19 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
Python程序慢的重要原因
2020/09/04 Python
总结Pyinstaller的坑及终极解决方法(小结)
2020/09/21 Python
Python Unittest原理及基本使用方法
2020/11/06 Python
python 解决Windows平台上路径有空格的问题
2020/11/10 Python
UNIX命令速查表
2012/03/10 面试题
护士见习期自我鉴定
2014/02/08 职场文书
农业局学习党的群众路线教育实践活动心得体会
2014/03/07 职场文书
2014镇党委班子对照检查材料思想汇报
2014/09/23 职场文书
莫言获奖感言(全文)
2015/07/31 职场文书
Python3使用Qt5来实现简易的五子棋小游戏
2022/05/02 Python