python – 使用pandas的“大数据”工作流程
作者:互联网
在学习大熊猫的过程中,我试图解决这个问题的答案已有好几个月了.我使用SAS进行日常工作,这非常适合它的核心支持.然而,由于其他许多原因,SAS作为一款软件非常糟糕.
有一天,我希望用python和pandas替换我对SAS的使用,但我目前缺乏大型数据集的核心工作流程.我不是在谈论需要分布式网络的“大数据”,而是说文件太大而无法容纳在内存中,但又足够小以适应硬盘驱动器.
我的第一个想法是使用HDFStore在磁盘上保存大型数据集,并仅将我需要的部分拉入数据帧进行分析.其他人提到MongoDB是一种更容易使用的替代品.我的问题是:
有哪些最佳实践工作流程可用于完成以下任务:
>将平面文件加载到永久的磁盘数据库结构中
>查询该数据库以检索数据以提供给pandas数据结构
>在操作pandas中的片段后更新数据库
真实世界的例子将非常受欢迎,尤其是那些在“大数据”上使用熊猫的人.
编辑 – 我希望如何工作的示例:
>迭代导入大型平面文件并将其存储在永久的磁盘数据库结构中.这些文件通常太大而无法放入内存中.
>为了使用Pandas,我想读取这些数据的子集(通常一次只有几列),它们可以适合内存.
>我将通过对所选列执行各种操作来创建新列.
>然后我必须将这些新列附加到数据库结构中.
我正在尝试找到执行这些步骤的最佳实践方法.阅读关于pandas和pytables的链接似乎附加一个新列可能是个问题.
编辑 – 特别回应杰夫的问题:
>我正在构建消费者信用风险模型.数据种类包括电话,SSN和地址特征;财产价值;犯罪记录,破产等贬损信息……我每天使用的数据集平均有近1,000到2,000个字段的混合数据类型:数字和字符数据的连续,名义和序数变量.我很少附加行,但我会执行许多创建新列的操作.
>典型操作涉及使用条件逻辑将多个列组合到新的复合列中.例如,如果var1> 2然后newvar =’A’elif var2 = 4则newvar =’B’.这些操作的结果是我的数据集中每条记录的新列.
>最后,我想将这些新列附加到磁盘上的数据结构中.我将重复第2步,使用交叉表和描述性统计数据探索数据,试图找到有趣,直观的模型关系.
>典型的项目文件通常约为1GB.文件被组织成一种行,其中一行包括消费者数据的记录.每行对每条记录都有相同的列数.情况总是如此.
>在创建新列时,我很少按行进行分组.但是,在创建报告或生成描述性统计信息时,对行进行子集化非常常见.例如,我可能想为特定的业务线创建一个简单的频率,比如零售信用卡.要做到这一点,除了我要报告的列之外,我只会选择那些业务线=零售的记录.但是,在创建新列时,我会提取所有数据行,只提取操作所需的列.
>建模过程要求我分析每一列,寻找与某些结果变量的有趣关系,并创建描述这些关系的新化合物列.我探索的列通常以小集合完成.例如,我将专注于一组20个列,只处理属性值并观察它们与贷款违约的关系.一旦探索了这些并创建了新的列,我就转到另一组列,比如大学教育,然后重复这个过程.我正在做的是创建候选变量来解释我的数据和某些结果之间的关系.在这个过程的最后,我应用了一些学习技术,从这些复合列中创建一个方程式.
我很少会在数据集中添加行.我几乎总是会创建新的列(统计/机器学习用语中的变量或特征).
解决方法:
我通常以这种方式使用数十亿字节的数据
例如我在磁盘上有表,我通过查询,创建数据和追加回读.
有关如何存储数据的若干建议,请阅读the docs和late in this thread.
详细信息将影响您存储数据的方式,例如:
尽可能多地提供细节;我可以帮你建立一个结构.
>数据大小,行数,列数,列类型;你在追加吗?
行,还是只是列?
>典型的操作是什么样的.例如.对列进行查询以选择一堆行和特定列,然后执行操作(内存中),创建新列,保存这些列.
(给出一个玩具示例可以让我们提供更具体的建议.)
>经过那个处理,那你做什么?第2步是临时的,还是可重复的?
>输入平面文件:Gb中有多少粗略的总大小.这些如何组织,例如按记录?每个文件是否包含不同的字段,或者每个文件中是否包含每个文件中包含所有字段的记录?
>您是否曾根据标准选择行(记录)的子集(例如,选择字段A> 5的行)?然后做一些事情,或者你只是选择包含所有记录的字段A,B,C(然后做一些事情)?
>您是否“处理”所有列(以组为单位),或者是否有一个很好的比例,您只能用于报告(例如,您希望保留数据,但不需要提取该列明确性直到最后的结果时间)?
解
确保已安装pandas at least 0.10.1
.
阅读iterating files chunk-by-chunk和multiple table queries.
由于pytables被优化为按行进行操作(这是您查询的内容),因此我们将为每组字段创建一个表.通过这种方式,可以轻松选择一小组字段(可以使用大表格,但这样做效率更高……我想我将来可以修复这个限制…这是无论如何更直观):
(以下是伪代码.)
import numpy as np
import pandas as pd
# create a store
store = pd.HDFStore('mystore.h5')
# this is the key to your storage:
# this maps your fields to a specific group, and defines
# what you want to have as data_columns.
# you might want to create a nice class wrapping this
# (as you will want to have this map and its inversion)
group_map = dict(
A = dict(fields = ['field_1','field_2',.....], dc = ['field_1',....,'field_5']),
B = dict(fields = ['field_10',...... ], dc = ['field_10']),
.....
REPORTING_ONLY = dict(fields = ['field_1000','field_1001',...], dc = []),
)
group_map_inverted = dict()
for g, v in group_map.items():
group_map_inverted.update(dict([ (f,g) for f in v['fields'] ]))
读取文件并创建存储(基本上执行append_to_multiple所做的事情):
for f in files:
# read in the file, additional options hmay be necessary here
# the chunksize is not strictly necessary, you may be able to slurp each
# file into memory in which case just eliminate this part of the loop
# (you can also change chunksize if necessary)
for chunk in pd.read_table(f, chunksize=50000):
# we are going to append to each table by group
# we are not going to create indexes at this time
# but we *ARE* going to create (some) data_columns
# figure out the field groupings
for g, v in group_map.items():
# create the frame for this group
frame = chunk.reindex(columns = v['fields'], copy = False)
# append it
store.append(g, frame, index=False, data_columns = v['dc'])
现在你已经拥有了文件中的所有表格(实际上你可以将它们存储在单独的文件中,如果你愿意,你可能需要将文件名添加到group_map,但可能这不是必需的).
这是您获取列并创建新列的方法:
frame = store.select(group_that_I_want)
# you can optionally specify:
# columns = a list of the columns IN THAT GROUP (if you wanted to
# select only say 3 out of the 20 columns in this sub-table)
# and a where clause if you want a subset of the rows
# do calculations on this frame
new_frame = cool_function_on_frame(frame)
# to 'add columns', create a new group (you probably want to
# limit the columns in this new_group to be only NEW ones
# (e.g. so you don't overlap from the other tables)
# add this info to the group_map
store.append(new_group, new_frame.reindex(columns = new_columns_created, copy = False), data_columns = new_columns_created)
当您准备进行post_processing时:
# This may be a bit tricky; and depends what you are actually doing.
# I may need to modify this function to be a bit more general:
report_data = store.select_as_multiple([groups_1,groups_2,.....], where =['field_1>0', 'field_1000=foo'], selector = group_1)
关于data_columns,您实际上不需要定义任何data_columns;它们允许您根据列子选择行.例如.就像是:
store.select(group, where = ['field_1000=foo', 'field_1001>0'])
在最终报告生成阶段,它们可能对您最感兴趣(实质上,数据列与其他列隔离,如果您定义了很多,这可能会影响效率).
您可能还想:
>创建一个获取字段列表的函数,查找groups_map中的组,然后选择这些并连接结果,以便得到结果帧(这实际上是select_as_multiple所做的).通过这种方式,结构对您来说非常透明.
>某些数据列上的索引(使行子集更快).
>启用压缩.
如果您有疑问,请告诉我!
标签:large-data,python,pandas,mongodb,hdf5 来源: https://codeday.me/bug/20190911/1802800.html