当前位置: 首页 > 面试题库 >

pandas groupby与sum()在大型csv文件上?

杭永安
2023-03-14
问题内容

我有一个大文件(约19GB),我想加载到内存中以对某些列执行聚合。

该文件如下所示:

id, col1, col2, col3, 
1 ,  12 , 15 , 13 
2 ,  18 , 15 , 13 
3 ,  14 , 15 , 13 
3 ,  14 , 185 , 213

请注意,在加载到数据帧后,我正在使用列(id,col1)进行聚合,还请注意,这些键可能会连续重复几次,例如:

3 ,  14 , 15 , 13 
3 ,  14 , 185 , 213

对于小文件,以下脚本可以完成此工作

import pandas as pd
data = pd.read_csv("data_file", delimiter=",")
data = data.reset_index(drop=True).groupby(["id","col1"], as_index=False).sum()

但是,对于大文件,我在读取csv文件时需要使用chunksize来限制加载到内存中的行数:

import pandas as pd
data = pd.read_csv("data_file", delimiter=",", chunksize=1000000)
data = data.reset_index(drop=True).groupby(["id","col1"], as_index=False).sum()

在后一种情况下,如果将(id,col1)相似的行拆分到不同的文件中,则会出现问题。我该如何处理?

编辑

正如@EdChum指出的那样,有一个潜在的解决方法,即 不只是将groupby结果附加到新的csv并读回并再次执行聚合,直到df大小不变。

但是,这有一个最坏的情况,无法处理,即:

当所有文件(或内存无法处理的足够多的文件)最后都具有相同的有问题的相似对象(id,col1)时。 这将导致系统返回MemoryError


问题答案:

首先,你可以通过读取CSV选与众不同的常量列表usecols - usecols=['id', 'col1']。然后按块读取csv,按id和groupby的子集读取concat块。

如果更好用列col1,就换constants = df['col1'].unique().tolist()。这取决于您的数据。

或者,您只能读取一列df = pd.read_csv(io.StringIO(temp), sep=",",usecols=['id']),这取决于您的数据。

import pandas as pd
import numpy as np
import io

#test data
temp=u"""id,col1,col2,col3
1,13,15,14
1,13,15,14
1,12,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
3,14,15,13
3,14,15,13
3,14,185,213"""
df = pd.read_csv(io.StringIO(temp), sep=",", usecols=['id', 'col1'])
#drop duplicities, from out you can choose constant
df = df.drop_duplicates()
print df
#   id  col1
#0   1    13
#2   1    12
#3   2    18
#9   3    14

#for example list of constants
constants = [1,2,3]
#or column id to list of unique values
constants = df['id'].unique().tolist()
print constants
#[1L, 2L, 3L]

for i in constants:
    iter_csv = pd.read_csv(io.StringIO(temp), delimiter=",", chunksize=10)
    #concat subset with rows id == constant
    df = pd.concat([chunk[chunk['id'] == i] for chunk in iter_csv])
    #your groupby function
    data = df.reset_index(drop=True).groupby(["id","col1"], as_index=False).sum()
    print data.to_csv(index=False)

    #id,col1,col2,col3
    #1,12,15,13
    #1,13,30,28
    #
    #id,col1,col2,col3
    #2,18,90,78
    #
    #id,col1,col2,col3
    #3,14,215,239


 类似资料:
  • 问题内容: 我正在使用Python脚本处理大型CSV文件(数以10M行的GB数)。 这些文件具有不同的行长,并且无法完全加载到内存中进行分析。 每行由脚本中的一个函数分别处理。分析一个文件大约需要20分钟,并且看来磁盘访问速度不是问题,而是处理/函数调用。 代码看起来像这样(非常简单)。实际的代码使用Class结构,但这是相似的: 鉴于计算需要共享的数据结构,使用多核在Python中并行运行分析的

  • 问题内容: 我需要构建一个函数来处理大型CSV文件,以便在bluebird.map()调用中使用。考虑到文件的潜在大小,我想使用流媒体。 此函数应接受一个流(一个CSV文件)和一个函数(处理该流中的块),并在读取文件到末尾(已解决)或错误(已拒绝)时返回promise。 所以,我开始: 现在,我有两个相互关联的问题: 我需要限制正在处理的实际数据量,以免造成内存压力。 作为参数传递的函数通常将是异

  • 我使用Dask读取2.5GB csv文件,Python给了我错误。这是我写的代码: 以下是我从Python得到的错误: dask_df=df1.read_csv('3SPACK_N150_7Ah_压力分布研究_Data_Matrix.csv')) 文件“C:\ProgramData\Anaconda3\lib\site packages\dask\dataframe\io\csv.py”,第645

  • 由于多值字段和维度使用报价,csv读取器读取此文件失败。我的函数(上面代码中的函数f)如果那个逗号在属于同一字段的两个数据之间,就用分号代替逗号,如果那个引号是维度的东西,就用'inch'代替。

  • 我需要将大型csv文件从node发送到Python。这段代码适用于小文件,但不适用于大文件。我也试过产卵过程。我不明白问题出在哪里。如果有人知道正确的代码,请分享 代码: 错误

  • 我从Google Bigquery中提取了一个2列1000万行的。csv文件。 我已经在本地下载了一个大小为170MB的.csv文件,然后将文件上传到Google Drive,我想使用pandas.read_csv()函数将其读入我的Jupyter笔记本中的pandas DataFrame。 这是我使用的代码,有我想读的特定文件ID。