草庐IT

python - "Large data"使用 Pandas 的工作流程

coder 2023-04-25 原文

几个月来,我在学习 Pandas 的过程中一直试图找出这个问题的答案。我在日常工作中使用 SAS,它的核心外支持非常棒。然而,由于许多其他原因,SAS 作为一款软件很糟糕。

有一天,我希望用 Python 和 Pandas 取代我对 SAS 的使用,但我目前缺乏用于大型数据集的核心外工作流程。我说的不是需要分布式网络的“大数据”,而是大到无法放入内存但小到可以放入硬盘的文件。

我的第一个想法是使用 HDFStore将大型数据集保存在磁盘上并仅将我需要的部分提取到数据帧中进行分析。其他人提到 MongoDB 是一种更易于使用的替代方案。我的问题是这样的:

完成以下工作的最佳实践工作流程有哪些:

  • 将平面文件加载到永久的磁盘数据库结构中
  • 查询该数据库以检索数据以提供给 Pandas 数据结构
  • 在 Pandas 中操作片段后更新数据库

  • 真实世界的例子将不胜感激,尤其是任何在“大数据”上使用 Pandas 的人。

    编辑 - 我希望它如何工作的一个例子:
  • 反复导入大型平面文件并将其存储在永久的磁盘数据库结构中。这些文件通常太大而无法放入内存。
  • 为了使用 Pandas,我想读取可以放入内存的数据子集(通常一次只有几列)。
  • 我将通过对所选列执行各种操作来创建新列。
  • 然后我必须将这些新列附加到数据库结构中。

  • 我正在尝试找到执行这些步骤的最佳实践方法。阅读有关 pandas 和 pytables 的链接似乎附加新列可能是一个问题。

    编辑——专门回答杰夫的问题:
  • 我正在构建消费者信用风险模型。数据类型包括电话、SSN 和地址特征;属性(property)值(value);诸如犯罪记录、破产等贬义信息……我每天使用的数据集平均有近 1,000 到 2,000 个字段,混合数据类型:数字和字符数据的连续、名义和有序变量。我很少追加行,但我确实执行了许多创建新列的操作。
  • 典型的操作包括使用条件逻辑将几个列组合成一个新的复合列。例如,if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B' .这些操作的结果是数据集中每条记录的新列。
  • 最后,我想将这些新列附加到磁盘数据结构中。我会重复第 2 步,使用交叉表和描述性统计探索数据,试图找到有趣、直观的模型关系。
  • 一个典型的项目文件通常约为 1GB。文件被组织成这样一种方式,其中一行由消费者数据的记录组成。对于每条记录,每一行具有相同数量的列。这将永远如此。
  • 在创建新列时,我很少会按行进行子集化。但是,在创建报告或生成描述性统计信息时,对行进行子集化是很常见的。例如,我可能想为特定业务线创建一个简单的频率,比如零售信用卡。为此,除了要报告的列之外,我将仅选择业务线 = 零售的那些记录。但是,在创建新列时,我会拉取所有数据行和操作所需的列。
  • 建模过程要求我分析每一列,寻找与某些结果变量的有趣关系,并创建描述这些关系的新复合列。我探索的专栏通常是小集完成的。例如,我将重点关注一组仅处理属性(property)值(value)的 20 列,并观察它们与贷款违约之间的关系。一旦探索了这些并创建了新的专栏,我就会转到另一组专栏,比如大学教育,并重复这个过程。我正在做的是创建候选变量来解释我的数据和某些结果之间的关系。在这个过程的最后,我应用了一些学习技术,从这些复合列中创建一个方程。

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

    最佳答案

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

    值得一读the docslate in this thread有关如何存储数据的一些建议。

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

  • 数据大小、行数、列数、列类型;你在追加
    行,还是只是列?
  • 典型的操作是什么样的。例如。对列进行查询以选择一堆行和特定列,然后执行操作(内存中),创建新列,保存这些。
    (给出一个玩具示例可以让我们提供更具体的建议。)
  • 处理完之后,你会怎么做?第 2 步是临时的还是可重复的?
  • 输入平面文件:多少个,大概的总大小(以 Gb 为单位)。这些是如何组织的,例如通过记录?每个文件都包含不同的字段,还是每个文件都有一些记录,每个文件中的所有字段都包含在内?
  • 您是否曾经根据条件选择行(记录)的子集(例如,选择字段 A > 5 的行)?然后做一些事情,或者你只是选择包含所有记录的字段 A、B、C(然后做一些事情)?
  • 您是否“处理”了所有列(以组为单位),或者是否有很大一部分可能仅用于报告(例如,您想保留数据,但不需要明确拉入该列,直到最终结果时间)?

  • 解决方案

    确保您有 pandas at least 0.10.1 安装。

    阅读 iterating files chunk-by-chunkmultiple 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 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,你实际上不需要定义任何 数据列;它们允许您根据列子选择行。例如。就像是:
    store.select(group, where = ['field_1000=foo', 'field_1001>0'])
    

    它们可能在最终报告生成阶段对您来说最有趣(本质上,一个数据列与其他列是分开的,如果您定义很多,这可能会影响效率)。

    您可能还想:
  • 创建一个函数,它接受一个字段列表,在 groups_map 中查找组,然后选择这些组并连接结果,以便获得结果帧(这本质上是 select_as_multiple 所做的)。这样结构对你来说就非常透明了。
  • 某些数据列上的索引(使行子集设置更快)。
  • 启用压缩。

  • 当您有问题时,请告诉我!

    关于python - "Large data"使用 Pandas 的工作流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14262433/

    有关python - "Large data"使用 Pandas 的工作流程的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

      我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

    3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

      很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

    5. ruby - 在 Ruby 中使用匿名模块 - 2

      假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

    6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

      我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

    7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    8. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    9. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

      我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

    10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    随机推荐