【问题标题】:Python / Pandas - Memory issue while applying a function on a huge dataframePython / Pandas - 在巨大的数据帧上应用函数时出现内存问题
【发布时间】:2018-03-26 20:26:37
【问题描述】:

我有一个包含 3.5 亿行、3 列的数据框

要求:

我想使用更少的内存根据管道符号将DESCRIPTION列拆分为LIST

input_df.head():

    startTime   DESCRIPTION                                                                                                                                     Response_Time
    1504212340  Business Transaction Performance|Business Transactions|Hexa|mBanking Confirmation.(Confirmation.aspx).no|Average Response Time (ms)_value       6
    1504212340  Business Transaction Performance|Business Transactions|Hexa|mBanking Frontpage.ci|Average Response Time (ms)_value                              4
    1504202341  Business Transaction Performance|Business Transactions|Hexa|mBanking Fonto KTList GenericNS.(GenericNS).dk|Average Response Time (ms)_value     5
    1504202341  Business Transaction Performance|Business Transactions|Hexa|mBanking Transaction Overview.co|Average Response Time (ms)_value                   5
    1504202342  Business Transaction Performance|Business Transactions|Hexa|mBanking Logon.(BidError.aspx).no|Average Response Time (ms)_value                  8

desired_output:

    startTime   list_Description                                                                                                                                             Response_Time
    1504212340  ['Business Transaction Performance', 'Business Transactions', 'Hexa', 'mBanking Confirmation.(Confirmation.aspx).no', 'Average Response Time (ms)_value']    6
    1504212340  ['Business Transaction Performance', 'Business Transactions', 'Hexa', 'mBanking Frontpage.ci', 'Average Response Time (ms)_value']                           4
    1504202341  ['Business Transaction Performance', 'Business Transactions', 'Hexa', 'mBanking Fonto KTList GenericNS.(GenericNS).dk', 'Average Response Time (ms)_value']  5
    1504202341  ['Business Transaction Performance', 'Business Transactions', 'Hexa', 'mBanking Transaction Overview.co', 'Average Response Time (ms)_value']                5
    1504202342  ['Business Transaction Performance', 'Business Transactions', 'Hexa', 'mBanking Logon.(BidError.aspx).no', 'Average Response Time (ms)_value']               8

我的代码:

    import pandas as pd
    import glob

    path = r'C:/Users/IBM_ADMIN/Desktop/Delete/Source/app_dynamics/*'    #500 csv files in this location
    all_files = glob.glob(path) 

    #Get the input files and concatenate   
    generator  = (pd.read_csv(f, delimiter='\t', dtype=float) for f in all_files)   #Using parentheses returns a generator instead of a list, mentioning 'dtype=float' helps to use less memory
    input_df   = pd.concat(generator , ignore_index=True)   #results in 350 million rows , 3 columns
    input_df['list_Description'] = input_df['DESCRIPTION'].str.split('|')  #Splitting the string into list

我的代码的缺点

上述代码适用于数据帧中较少的行数。但是如果我将它应用于 3.5 亿行,我的内存会立即达到 98% 并且系统会挂起。

csv 可能有帮助.. 但是

如果我在 csv 文件中有“input_df”,则可以分块处理(顺便说一句,在这种情况下,我不想将“input_df”写入 csv :-))。由于上面的“input_df”是一个数据框,我不知道如何开始。如果有办法直接在数据帧上使用块大小会很好

请问有人可以提供一个更好的主意来避免内存问题吗?

【问题讨论】:

  • 这是一个长镜头,但您的专栏中有多少独特的价值。你能发布输出:input_df.DESCRIPTION.nunique()
  • input_df.DESCRIPTION.nunique() 输出[43]: 3445

标签: python pandas dataframe memory-management chunks


【解决方案1】:

我不能保证这会奏效,因为我没有相同的数据来测试它,但是你可以在阅读时对块应用分割功能,这样你就没有将那巨大的列在内存中保存两次?

修改您的代码,您可以尝试以下方法:

import pandas as pd
import glob

path = r'C:/Users/IBM_ADMIN/Desktop/Delete/Source/app_dynamics/*'    #500 csv files in this location
all_files = glob.glob(path) 

def read_and_split(f):
    chunk = pd.read_csv(f, delimiter='\t', dtype=float)
    chunk['list_Description'] = chunk['DESCRIPTION'].str.split('|')
    return chunk.drop('DESCRIPTION', axis=1)

#Get the input files and concatenate   
generator  = (read_and_split(f) for f in all_files)   #Using parentheses returns a generator instead of a list, mentioning 'dtype=float' helps to use less memory
input_df   = pd.concat(generator, ignore_index=True)   #results in 350 million rows , 3 columns

如果这仍然不起作用,您可以查看Dask,它允许您以分布式容量存储非常大的 DataFrame。

【讨论】:

  • 对不起。上面的代码也达到了 99% 的内存。正如你所说,我会检查 Dask
【解决方案2】:

由于看起来DESCRIPTION 列包含很多重复值,您可以像这样构建一个查找表:

lookup = input_df.DESCRIPTION.drop_duplicates().reset_index()
lookup = lookup.reset_index().rename(columns={'index': 'description_id'})
input_df = input_df.merge(lookup, on='DESCRIPTION')
lookup = pd.concat([lookup, lookup.DESCRIPTION.str.split('|', expand=True)],
                   axis=1)

此时您可以删除lookupinput_df 中的DESCRIPTION 列,因为所有必要的信息都包含在lookup 数据框的列中。

input_df.drop('DESCRIPTION', axis=1, inplace=True)
lookup.drop('DESCRIPTION', axis=1, inplace=True)

input_df 现在将有一个description_id 列,它告诉您lookup 数据框的哪一行包含从DESCRIPTION 中提取的信息。

【讨论】:

  • Yuri,我无法删除 DESCRIPTION 列的重复项,因为它具有 'Response_Time' 值,这些值会因各自的 'startTime' 而不同
  • input_df.DESCRIPTION.str.extract 提取“Response_Time”值怎么样?
猜你喜欢
  • 2020-10-03
  • 2018-09-15
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 2019-08-26
  • 2018-08-19
相关资源
最近更新 更多