# coding: utf-8
import os
import re
def parserln(ln, patt):
"""用给定的正则表达式解析行"""
matched = patt.match(ln)
if matched:
return matched.groupdict()
def getdata(filename, parser, callback=None):
"""用指定的解析方法parser解析指定文件,
用callback进行数据加工过的数据列表
"""
with open(filename, 'rt'胡侍) as handle:
return map(
callback,
filter(None, map(parser, handle))
)
def storage(filename, dataserial, spliter=','):
"""将数据序列按行存储到指定文件,
每一序列元素间用指定的字符分割"""
with open(filename, 'wt') as handle:
handle.writelines([
"%s\n" % (spliter.join(map(str, item)))
for item in dataserial
])
if __name__ == "__main__":
patt = re.compile(
r"""^
(?P<month>\d+),
(?P<amount>\d+),
(?P<usage>\d+)
\s*$""",
仿做兄re.I | re.U | re.X)
datapath = 'datasource'
# datasource下所有存在"usage.csv"文件的子目录
subpaths = [
os.path.join(datapath, path)
for path in os.listdir(datapath)
if (os.path.isdir(os.path.join(datapath, path))
备袭 and os.path.exists(
os.path.join(datapath, path, "usage.txt"))
)
]
storage(
'store.csv',
zip(*map(
lambda path: getdata(
os.path.join(path, "usage.csv"),
# 解析方法为用patt解析行
parser=lambda ln: parserln(ln, patt),
# 数据加工方法是取出"amount"转成整数
callback=lambda x: int(x["amount"]),
),
subpaths))
)
$ tail -n 12 datasource/*/*.csv
==>datasource/2014/usage.csv <==
1,4234,423
2,3523,432
3,4352,438
4,4792,458
5,4823,834
6,5093,734
7,4743,832
8,5152,859
9,4932,810
10,4993,802
11,4999,810
12,5052,850
==>datasource/2015/usage.csv <==
1,5234,423
2,4523,432
3,5352,438
4,5792,458
5,6823,834
6,6093,734
7,6743,832
8,7152,859
9,6932,810
10,6993,802
11,6999,810
12,7052,850
(venv)tim@crunchbang:~/workspace/baidu$
$ cat store.csv
4234,5234
3523,4523
4352,5352
4792,5792
4823,6823
5093,6093
4743,6743
5152,7152
4932,6932
4993,6993
4999,6999
5052,7052
$
csv文件应正肢该是用逗号分隔得才对,否则怎么算作是csv文件。楼主你开玩笑吧。否则你这只是一个普通的文本文件。如果是真正的csv文件,我只说一点,python里面有csv模块,专门处理csv文件。如果是空格分割应该也可以,建议你,看一下python的csv模块的API,蛮简单的代码,其旦团实如果不用的话自己写也可以。不是很复杂。代码片段如下:
def deal_file(file_in, file_out)with open(file_in, 'r') as f_in:
with open(file_out, 'w') as f_out:
for line in f_in:
f_out.write(line.split(' ')[2] + '\n')
之后你可以将所有的输入文件放到一个列表里举迟世面,进行迭代调用这个函数就可以了。
在新的作业中,将电影元数据文件作为tFileInputDelimited组件添加到作业中。
注意,电影文件中的最后一列是DirectorID。在本教程中,使用此列将电影文件加入Directors文件中的directorID列。
1. 创建一个新的带分隔符的元数据文件,名为Directors。
2. 要指定示例文件,请单击“文件”字段旁边的“ 浏览”,从本地磁盘中选择文件txt,然后单击“ 打开”。
3. 此文件中的字段分隔符是逗号。要更改定界符耐漏前,请在“字段分隔符”下拉列表中选择“逗号”。
4. 要刷新文件显示以反映所做的更改,请单击刷新预览。注意:此文件只有两列:DirectorID和DirectorName。
5. 将列名称更改为directorID和directorName,将directorName字段的长度更改为40。新的元数据文件director 0.1将显示在项目存储库中的“元数据”下。现在,您可以将movie文件中的directorID列与director文件中的directorID列连接在一起。
6. 将控制器元数据文件添加到作业中作为第二个源输入。
1. 将tMap组件添加到作业设计器。
2. 要在两个组件之间建立到tMap组件的数据流,请首先将影片链接到tMap_1组件,然后将导演链接到tMap_1。
3. 要重命名源组件和tMap组件之间的链接,请两次单击该链接,然后键入movie。同样,将另一个链接重命名为Directors。
4. 要打开tMap组件向导,请双击该组件。请注意,在向导的左侧部分,电影和导演都被列为tMap组件的输入。
5. 要创建新的输出数据流,请在tMap向导的输出部分中,单击[+]将新输出命名为joinedOutput,然后单击OK。创建空白输出数据流。
6. 要将movieID,title,releaseYear和url字段添加到输出数据流,从movie输入中选择四个字段,并将它们放在输出数据流中。
同样,将directorName字段也添加到输出数据流中,从director输入中选择这个字段拖到输出数据流中。
7. 要配置联接,在movies表中选择directorID列,并将其拖到director表的directorID列中。
1. 要为输出指定目标,请在作业设计器中添加一个tFileOutputDelimited组件,然后将tMap组件的joindOutput输出链接到它。
2. 要配置输出组件,请在组件的“组件”视图中,指定输出文件的路径和名称,并在输出文件中包含标题行。
3. 要运行作业,请在“运行”视图中单击“运行”。
4. 要检查moviesComplete.csv文件,请导航至创建该文件的文件夹并打开该文件。
5. 注意:某些电影没有显示导演姓名。这些电影没有导演ID。
6. ETL工具中的默认行为搜脊:
l 将显示行驶表中的所有行。
l 如果昌清不满足加入条件,则相应的输出字段将为空白。这是“左外部联接”。相反,您可以在tMap中将联接配置为内部联接,该联接仅显示满足联接条件的行。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)