在学习大Pandas 的过程中,我已经try 了好几个月来寻找这个问题的答案.我在日常工作中使用SAS,这非常好,因为它提供了核心外的支持.然而,SAS作为软件的一部分,由于许多其他原因是可怕的.

有一天,我希望用python和pandas取代SAS的使用,但我目前缺乏大型数据集的核心工作流程.我说的不是需要分布式网络的" Big Data ",而是文件太大,无法放入内存,但小到可以装入硬盘.

我的第一个 idea 是使用HDFStore在磁盘上保存大型数据集,并且只将我需要的部分放入数据帧中进行分析.其他人提到MongoDB是一个更容易使用的 Select .我的问题是:

实现以下目标的一些最佳实践工作流有哪些:

  1. 将平面文件加载到永久的磁盘数据库 struct 中
  2. 查询该数据库以检索要馈送到Pandas 数据 struct 中的数据
  3. 在处理Pandas 的碎片后更新数据库

现实世界中的例子将非常受欢迎,尤其是那些在" Big Data "中使用Pandas 的人.

编辑——一个我希望它如何工作的例子:

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

我正试图找到执行这些步骤的最佳实践方式.阅读关于pandas和pytables的链接似乎添加一个新的专栏可能会有问题.

编辑——具体回答杰夫的问题:

  1. 我正在建立消费者信用风险模型.这些数据包括电话、SSN和地址特征;财产价值;犯罪记录、破产等贬损信息……我每天使用的数据集平均有近1,000到2,000个混合数据类型的字段:数字和字符数据的连续变量、名义变量和顺序变量.我很少追加行,但我确实执行了许多创建新列的操作.
  2. 典型的操作包括使用条件逻辑将多个列组合成一个新的复合列.例如,if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'.这些操作的结果是数据集中的每个记录都有一个新列.
  3. 最后,我想将这些新列附加到磁盘数据 struct 中.我会重复第2步,用交叉表和描述性统计数据探索数据,试图找到有趣、直观的模型关系.
  4. 典型的项目文件通常约为1 GB.文件被组织成这样的方式,其中一行由消费者数据的记录组成.对于每条记录,每行都有相同数量的列.这种情况永远不会改变.
  5. 在创建新列时,我很少按行设置子集.但是,在创建报告或生成描述性统计信息时,对行设置子集对我来说是很常见的.例如,我可能想为特定的业务线(比如零售信用卡)创建一个简单的频率.为此,除了要报告的任何列之外,我还将只 Select 业务线=RETAIL的那些记录.但是,在创建新列时,我会拉出所有数据行,只拉出操作所需的列.
  6. 建模过程要求我分析每一列,寻找与某些结果变量的有趣关系,并创建描述这些关系的新复合列.我研究的专栏通常都是小规模的.例如,我将重点关注一组(比如20列)只涉及房产价值的列,并观察它们与贷款违约的关系.一旦对这些内容进行了探索并创建了新的专栏,我就会转到另一组专栏,比如大学教育,然后重复这个过程.我所做的是创建候选变量,解释我的数据和某些结果之间的关系.在这个过程的最后,我应用了一些学习技巧,从这些复合列中创建一个等式.

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

推荐答案

我经常以这种方式使用数十GB的数据

关于如何存储数据的几点建议,值得阅读the docslate in this thread.

Details which will affect how you store your data, like:
Give as much detail as you can; and I can help you develop a structure.

  1. 数据大小、行数、列数、列类型;是否要追加 行,还是只列?
  2. 典型的操作会是什么样子.例如,对列执行查询以 Select 一组行和特定列,然后执行操作(在内存中),创建新列,保存这些列
  3. 处理完之后,你会做什么呢?步骤2是临时的,还是可重复的?
  4. 输入平面文件:数量,大致总大小(Gb).这些是如何组织的,例如通过记录?是每个文件都包含不同的字段,还是每个文件都有一些记录,其中包含每个文件中的所有字段?
  5. Do you ever select subsets of rows (records) based on criteria (e.g. select the rows with field A > 5)? and then do something, or do you just select fields A, B, C with all of the records (and then do something)?
  6. 你是否"处理"了你所有的专栏(分组),或者你是否有一个很好的比例可以只用于报告(例如,你想保留数据,但在最终结果之前不需要明确地拉入该专栏)?

解决方案

Ensure you have 100 installed.

阅读iterating files chunk-by-chunkmultiple table queries.

由于pytables已优化为按行操作(这是您查询的内容),因此我们将为每组字段创建一个表.这样就可以很容易地 Select 一小组字段(适用于大表格,但这样做效率更高…….)我想我将来也许能解决这个限制……这无论如何更直观):
(以下是伪代码.)

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'])

现在文件中有了所有的表(实际上,如果愿意,可以将它们存储在单独的文件中,可能需要将文件名添加到组映射中,但这可能不是必需的).

下面是获取列和创建新列的方法:

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)

当您准备好进行后期处理时:

# 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,实际上不需要定义ANY个DATA_COLUMNS;它们允许您根据列再 Select 行.例如,类似于:

store.select(group, where = ['field_1000=foo', 'field_1001>0'])

在最终报告生成阶段,它们可能对您最感兴趣(基本上,一个数据列与其他列是分离的,如果您定义了很多,这可能会在一定程度上影响效率).

您可能还希望执行以下操作:

  • 创建一个函数,该函数获取字段列表,在groups_映射中查找组,然后 Select 这些组并连接结果,从而得到结果帧(这基本上就是select_as_multiple所做的).This way the structure would be pretty transparent to you.
  • 某些数据列上的索引(使行子集设置更快).
  • 启用压缩.

如果有问题,请告诉我!

Python相关问答推荐

Python 3.12中的通用[T]类方法隐式类型检索

运行回文查找器代码时发生错误:[类型错误:builtin_index_or_system对象不可订阅]

将整组数组拆分为最小值与最大值之和的子数组

对某些列的总数进行民意调查,但不单独列出每列

PywinAuto在Windows 11上引发了Memory错误,但在Windows 10上未引发

将pandas Dataframe转换为3D numpy矩阵

django禁止直接分配到多对多集合的前端.使用user.set()

为什么抓取的HTML与浏览器判断的元素不同?

合并帧,但不按合并键排序

考虑到同一天和前2天的前2个数值,如何估算电力时间序列数据中的缺失值?

为什么numpy. vectorize调用vectorized函数的次数比vector中的元素要多?

跳过嵌套JSON中的级别并转换为Pandas Rame

如何在Python中使用Iscolc迭代器实现观察者模式?

如何将相同组的值添加到嵌套的Pandas Maprame的倒数第二个索引级别

Python日志(log)库如何有效地获取lineno和funcName?

在MongoDB文档中仅返回数组字段

如何在表单中添加管理员风格的输入(PDF)

如何删除剪裁圆的对角线的外部部分

大Pandas 中的群体交叉融合

GEKKO中若干参数的线性插值动态优化