当前位置: 首页 > 知识库问答 >
问题:

使用pandas的“大数据”工作流

干浩阔
2023-03-14

几个月来,我在学习熊猫的过程中,一直在努力想出这个问题的答案。我在日常工作中使用SAS,它的核心支持很棒。然而,SAS作为一个软件是可怕的,还有许多其他原因。

有一天我希望用python和pandas取代我对SAS的使用,但我目前缺少一个用于大型数据集的非核心工作流。我说的不是需要分布式网络的“大数据”,而是大到内存放不下但小到硬盘驱动器放不下的文件。

我的第一个想法是使用hdfstore在磁盘上保存大型数据集,并只将所需的部分放入数据流中进行分析。其他人提到MongoDB是一个更容易使用的替代方案。我的问题是:

完成以下工作的一些最佳实践工作流程是什么:

  1. 将平面文件加载到永久的磁盘上数据库结构
  2. 查询该数据库以检索数据以输入pandas数据结构
  3. 在Pandas中操作片段后更新数据库

真实世界的例子将非常感谢,特别是从任何谁使用熊猫的“大数据”。

编辑--我希望它如何工作的示例:

  1. 反复导入大型平面文件,并将其存储在永久的磁盘数据库结构中。这些文件通常太大,内存放不下。
  2. 为了使用Pandas,我想读取内存中可以容纳的该数据的子集(通常一次只读取几列)。
  3. 我将通过对所选列执行各种操作来创建新列。
  4. 然后必须将这些新列追加到数据库结构中。

我正试图找到一种执行这些步骤的最佳实践方法。阅读有关熊猫和pytables的链接时,添加一个新的专栏似乎是个问题。

编辑--专门回答Jeff的问题:

  1. 我正在建立消费信贷风险模型。数据种类包括电话、SSN和地址特征;财产价值;像犯罪记录、破产等贬损性的信息。我每天使用的数据集平均有将近1000到2000个混合数据类型的字段:数值和字符数据都是连续的、标称的和序数的变量。我很少追加行,但我确实执行了许多创建新列的操作。
  2. 典型的操作包括使用条件逻辑将几个列组合成一个新的复合列。例如,如果var1>2,则newvar='a';如果var2=4,则newvar='b'。这些操作的结果是数据集中的每个记录都有一个新列。
  3. 最后,我想将这些新列追加到磁盘数据结构中。我将重复步骤2,使用交叉表和描述性统计数据来探索数据,试图找到有趣的、直观的关系来建模。
  4. 典型的项目文件通常约为1GB。文件被组织成这样一种方式,即一行由使用者数据记录组成。对于每条记录,每行的列数相同。永远都是这样。
  5. 在创建新列时,我很少会按行进行子集。然而,在创建报表或生成描述性统计信息时,对行进行子集是非常常见的。例如,我可能想为一个特定的业务线创建一个简单的频率,比如零售信用卡。为此,除了要报告的列之外,我将只选择那些业务线=retail的记录。然而,在创建新列时,我将提取所有数据行,并且只提取操作所需的列。
  6. 建模过程要求我分析每个列,寻找具有某些结果变量的有趣关系,并创建描述这些关系的新复合列。我探索的专栏通常是在小集合中完成的。例如,我将集中讨论一组大约20个专栏,只讨论财产价值,并观察它们与贷款违约之间的关系。一旦探索了这些内容并创建了新的专栏,我就会转到另一组专栏,比如大学教育,并重复这一过程。我所做的是创建候选变量来解释我的数据和某些结果之间的关系。在这个过程的最后,我应用了一些学习技巧,从这些复合列中创建一个等式。

我很少会向数据集中添加行。我几乎总是在创建新的列(统计学/机器学习术语中的变量或特性)。

共有3个答案

翁翰
2023-03-14

现在,在这个问题发生两年后,又出现了一只“出格”的熊猫:达斯克。太棒了!虽然它并不支持pandas的所有功能,但你可以在这方面做得很好。更新:在过去的两年中,它得到了持续的维护,并且有大量的用户社区在使用Dask。

现在,在这个问题四年后,又有一个高性能的“核心外”熊猫等价物在Vaex。它“使用内存映射、零内存复制策略和惰性计算以获得最佳性能(没有内存浪费)。”它可以处理数十亿行的数据集,并且不将其存储到内存中(使得甚至可以在次优硬件上进行分析)。

蔚琦
2023-03-14

我认为上面的答案缺少了一个我发现非常有用的简单方法。

当我有一个文件太大而无法加载到内存中时,我会将该文件分解为多个较小的文件(按行或按列)

示例:如果30天的交易数据大小为30GB,我将其分解为每天1GB大小的文件。我随后分别处理每个文件,并在最后汇总结果

最大的优点之一是它允许并行处理文件(多线程或进程)

另一个优点是文件操作(如本例中的添加/删除日期)可以通过常规shell命令完成,这在更高级/复杂的文件格式中是不可能的

这种方法并不涵盖所有场景,但在许多场景中都非常有用

栾峰
2023-03-14

我经常以这种方式使用几十GB的数据,例如,我在磁盘上有通过查询读取的表,创建数据并追加回来。

有必要阅读本文后面的文档,了解如何存储数据的几个建议。

将影响数据存储方式的详细信息,例如:
尽可能提供详细信息;我可以帮你建立一个结构。

  1. 数据大小、行数、列数、列类型;您是追加行还是只追加列?
  2. 典型操作是什么样子的。例如。查询列以选择一组行和特定列,然后执行操作(在内存中),创建新列并保存这些列。
    (给出一个玩具示例可以使我们提供更具体的建议。)
  3. 处理完之后,你做什么?步骤2是临时的还是可重复的?
  4. 输入平面文件:多少,粗略的总大小,单位为GB。这些是如何组织的,例如通过记录?是每个文件都包含不同的字段,还是每个文件都包含一些包含所有字段的记录?
  5. 您是否曾经根据条件选择行(记录)的子集(例如,选择字段A>5的行)?然后执行某些操作,还是只选择包含所有记录的字段A、B、C(然后执行某些操作)?
  6. 您是否“处理”所有列(分组),或者是否有一个很好的比例可以仅用于报表(例如,您希望保留数据,但不需要在最终结果时间之前将该列明确地拉入)?

确保至少安装了pandas0.10.1

逐块读取迭代文件和多个表查询。

由于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 may 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所做的工作)。这样结构对您来说就相当透明了。
  • 对某些数据列进行索引(使行子集更快)。
  • 启用压缩。

有问题的时候告诉我!

 类似资料:
  • 问题内容: 在学习pandas的过程中,我试图迷惑了这个问题很多月。我在日常工作中使用SAS,这非常有用,因为它提供了核心支持。但是,由于许多其他原因,SAS作为一个软件还是很糟糕的。 有一天,我希望用python和pandas取代我对SAS的使用,但是我目前缺少大型数据集的核心工作流程。我并不是说需要分布式网络的“大数据”,而是文件太大而无法容纳在内存中,但文件又足够小而无法容纳在硬盘上。 我的

  • 在学习熊猫的过程中,我已经尝试了好几个月来找出这个问题的答案。我在日常工作中使用SAS,这是非常好的,因为它提供了非核心支持。然而,SAS作为一个软件是可怕的,原因还有很多。 有一天,我希望用python和pandas取代SAS的使用,但我目前缺乏大型数据集的核心外工作流。我说的不是需要分布式网络的“大数据”,而是文件太大而无法放入内存,但又太小而无法装入硬盘。 我的第一个想法是使用将大型数据集保

  • 在学习熊猫的过程中,我已经尝试了好几个月来找出这个问题的答案。我在日常工作中使用SAS,这是非常好的,因为它提供了非核心支持。然而,SAS作为一个软件是可怕的,原因还有很多。 有一天,我希望用python和熊猫取代SAS,但我目前缺乏大型数据集的核心外工作流。我说的不是需要分布式网络的“大数据”,而是文件太大,无法放入内存,但又小到足以放入硬盘。 我的第一个想法是使用在磁盘上保存大型数据集,只将我

  • 我正在使用谷歌工作表来保存共享项目的数据。我使用Google的Sheets API访问数据,用python处理数据,并尝试在function writer中使用batchUpdate更新Sheets文件。 如果我将此函数数据作为列表传递,它将按预期工作 GoogleapClient。错误。HttpError: 任何指点都将不胜感激。

  • 问题内容: 我试图使用s或函数读取稍大的数据集,但我一直遇到s。数据框的最大大小是多少?我的理解是,只要数据适合内存,数据帧就应该可以,这对我来说不是问题。还有什么可能导致内存错误? 就上下文而言,我试图在《2007年消费者金融调查》中阅读ASCII格式(使用)和Stata格式(使用)。该文件的dta大小约为200MB,而ASCII的大小约为1.2GB,在Stata中打开该文件将告诉我,对于22,

  • 作为一个长期的SAS用户,我正在探索切换到python和pandas。 然而,在今天运行一些测试时,我很惊讶python在尝试一个128MB的csv文件时内存耗尽。它大约有200,000行和200列,大部分是数字数据。 使用SAS,我可以将csv文件导入SAS数据集,并且它可以和我的硬盘一样大。 中有类似的内容吗? 我经常处理大文件,没有访问分布式计算网络的权限。