在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 2.7.x 和 3.x 版本的重要区别小结
Nov 28 Python
python uuid模块使用实例
Apr 08 Python
Python版微信红包分配算法
May 04 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 27 Python
在python中实现对list求和及求积
Nov 14 Python
对python调用RPC接口的实例详解
Jan 03 Python
Python判断变量名是否合法的方法示例
Jan 28 Python
Django 使用easy_thumbnails压缩上传的图片方法
Jul 26 Python
python实现飞行棋游戏
Feb 05 Python
Python内存泄漏和内存溢出的解决方案
Sep 26 Python
Pandas对每个分组应用apply函数的实现
Dec 13 Python
详细介绍python类及类的用法
May 31 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
PHP PDOStatement::debugDumpParams讲解
2019/01/30 PHP
随机显示经典句子或诗歌的javascript脚本
2007/08/04 Javascript
JavaScript入门教程(3) js面向对象
2009/01/31 Javascript
html 锁定页面(js遮罩层弹出div效果)
2009/10/27 Javascript
jquery键盘事件介绍
2011/01/31 Javascript
jQuery代码优化 遍历篇
2011/11/01 Javascript
Javascript开发之三数组对象实例介绍
2012/11/12 Javascript
浅谈js 闭包引起的内存泄露问题
2015/06/22 Javascript
Active控件问题小结(附解决办法)
2016/06/09 Javascript
JS实现动态表格的添加,修改,删除功能(推荐)
2016/06/15 Javascript
AngularJS基础 ng-open 指令简单实例
2016/08/02 Javascript
基于JavaScript实现自定义滚动条
2017/01/25 Javascript
AngularJS 前台分页实现的示例代码
2018/06/07 Javascript
JS 实现获取验证码 倒计时功能
2018/10/29 Javascript
Node.js一行代码实现静态文件服务器的方法步骤
2019/05/07 Javascript
VUE前端从后台请求过来的数据进行转换数据结构操作
2020/11/11 Javascript
[03:54]DOTA2英雄梦之声_第06期_昆卡
2014/06/23 DOTA
python解析中国天气网的天气数据
2014/03/21 Python
Python实现可获取网易页面所有文本信息的网易网络爬虫功能示例
2018/01/15 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
python处理自动化任务之同时批量修改word里面的内容的方法
2019/08/23 Python
Python Des加密解密如何实现软件注册码机器码
2020/01/08 Python
如何在Windows中安装多个python解释器
2020/06/16 Python
一份全面的PHP面试问题考卷
2012/07/15 面试题
工程造价专业大学生职业生涯规划书
2014/01/18 职场文书
个性与发展自我评价
2014/02/11 职场文书
教育技术学专业职业规划书
2014/03/03 职场文书
市场部经理岗位职责
2014/04/10 职场文书
2015年保安个人工作总结
2015/04/02 职场文书
全国劳模先进事迹材料(2016精选版)
2016/02/25 职场文书
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python
Python并发编程实例教程之线程的玩法
2021/06/20 Python
JavaScript实现简单拖拽效果
2021/09/15 Javascript
Python echarts实现数据可视化实例详解
2022/03/03 Python
Tomcat starup.bat 脚本实现开机自启动
2022/04/20 Servers
Python何绘制带有背景色块的折线图
2022/04/23 Python