petl簡介
petl是使用原生python編寫的ETL包,數據操作邏輯簡單,但是處理數據的速度較慢。
ETL pipelines
petl包使用了大量的迭代器和延遲計算,在沒有請求函數請求數據時,pipelines 不會開始處理數據。
import petl as etl
table1 = etl.fromcsv('example.csv')
table2 = etl.convert(table1, 'foo', 'upper')
table3 = etl.convert(table2, 'bar', int)
table4 = etl.convert(table3, 'baz', float)
table5 = etl.addfield(table4, 'quux', lambda row: row.bar * row.baz)
petl.util.vis.look(),petl.io.csv.tocsv(),petl.io.text.totext(),petl.io.sqlite3.tosqlite3(),petl.io.db.todb()這些都是請求函數。執行請求函數后,根據pipelines ,順序地處理數據。
etl.look(table5)
面向對象編程
petl支持函數式和面向對象編程,例如
>>> import petl as etl
>>> table = (
... etl
... .fromcsv('example.csv')
... .convert('foo', 'upper')
... .convert('bar', int)
... .convert('baz', float)
... .addfield('quux', lambda row: row.bar * row.baz)
... )
>>> table.look()
petl中的wrap()函數,可以把有效表容器數據轉化為表結構數據
>>> l = [['foo', 'bar'], ['a', 1], ['b', 2], ['c', 2]]
>>> table = etl.wrap(l)
>>> table.look()
+-----+-----+
| foo | bar |
+=====+=====+
| 'a' | 1 |
+-----+-----+
| 'b' | 2 |
+-----+-----+
| 'c' | 2 |
+-----+-----+
交互式使用
交互式環境使用petl時,對象表達默認調用petl.util.vis.look()函數
>>> l = [['foo', 'bar'], ['a', 1], ['b', 2], ['c', 2]]
>>> table = etl.wrap(l)
>>> table
+-----+-----+
| foo | bar |
+=====+=====+
| 'a' | 1 |
+-----+-----+
| 'b' | 2 |
+-----+-----+
| 'c' | 2 |
+-----+-----+
默認調用時使用repr() 函數,以數值型方式打印數據,使用print函數,使用str(),以字符串方式打印數據
>>> print(table)
+-----+-----+
| foo | bar |
+=====+=====+
| a | 1 |
+-----+-----+
| b | 2 |
+-----+-----+
| c | 2 |
+-----+-----+
從操作系統調用petl腳本
$ petl "dummytable().tocsv()" > example.csv
$ cat example.csv | petl "fromcsv().cut('foo', 'baz').convert('baz', float).selectgt('baz', 0.5).head().data().totsv()"
提供一個位置參數"example.csv"給執行函數
表容器和表迭代器
表容器:
- 實現了__iter__ 方法
- __iter__ 返回一個表迭代器
- _ iter 返回的所有表迭代器都是獨立的,也就是說,從一個迭代器中消耗項不會影響其他迭代器
表迭代器:
- 迭代器返回的每個項都是一個序列(例如,元組或列表)
- 迭代器返回的第一個項是包含一系列標題值的標題行
- 迭代器返回的每個后續項都是由一系列數據值組成的數據行
- 標題值通常是字符串(str) ,但是可以是任何類型的對象,只要它實現了 __ str__ 並且可以選擇
- 數據值是任何可以取出的對象
例如:
>>> table = [['foo', 'bar'], ['a', 1], ['b', 2]]
table是有效的表容器,實現了__iter__ 方法,返回一個迭代器,第一個項是標題值['foo', 'bar'],后續是數據值['a', 1]和['b', 2]。
要求表容器支持獨立的表迭代器(第3點)的主要原因是,來自表的數據可能需要在同一個程序或交互會話中進行多次迭代。例如,當在交互式會話中使用 petl 建立一系列數據轉換步驟時,用戶可能希望在定義所有步驟和完整執行轉換之前檢查來自幾個中間步驟的輸出。
擴展-集成自定義數據源
Io 模塊具有從許多已知數據源中提取數據的功能。但是,編寫支持與其他數據源集成的擴展也很簡單。為了使對象可用作 petl 表,它必須實現上面描述的表容器約定。下面是 ArrayView 類的源代碼,該類允許將 petl 與 numpy 數組集成。這個類包含在 petl.io.numpy 模塊中,但是也提供了一個如何集成其他數據源的例子:
>>> import petl as etl
>>> class ArrayView(etl.Table):
... def __init__(self, a):
... # assume that a is a numpy array
... self.a = a
... def __iter__(self): # 實現了__iter__ 方法
... # yield the header row
... header = tuple(self.a.dtype.names) # 迭代器返回的第一個項是包含一系列標題值的標題行
... yield header # 是一個迭代器
... # yield the data rows
... for row in self.a:
... yield tuple(row) # 迭代器返回的每個后續項都是由一系列數據值組成的數據行
此類允許將numpy數組與petl函數一起使用
>>> import numpy as np
>>> a = np.array([('apples', 1, 2.5),
... ('oranges', 3, 4.4),
... ('pears', 7, 0.1)],
... dtype='U8, i4,f4')
>>> t1 = ArrayView(a)
>>> t1
+-----------+----+-----------+
| f0 | f1 | f2 |
+===========+====+===========+
| 'apples' | 1 | 2.5 |
+-----------+----+-----------+
| 'oranges' | 3 | 4.4000001 |
+-----------+----+-----------+
| 'pears' | 7 | 0.1 |
+-----------+----+-----------+
>>> t2 = t1.cut('f0', 'f2').convert('f0', 'upper').addfield('f3', lambda row: row.f2 * 2)
>>> t2
+-----------+-----------+---------------------+
| f0 | f2 | f3 |
+===========+===========+=====================+
| 'APPLES' | 2.5 | 5.0 |
+-----------+-----------+---------------------+
| 'ORANGES' | 4.4000001 | 8.8000001907348633 |
+-----------+-----------+---------------------+
| 'PEARS' | 0.1 | 0.20000000298023224 |
+-----------+-----------+---------------------+
只要t1符合表容器的定義,就可以使用petl的函數和管道