it-swarm.asia

خطأ في الذاكرة عند استخدام الباندا read_csv

أحاول القيام بشيء بسيط إلى حد ما ، قراءة ملف CSV كبير إلى dataframe الباندا.

data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)

الرمز يفشل إما مع MemoryError ، أو لا ينتهي أبدًا.

توقف استخدام Mem في إدارة المهام عند 506 ميغابايت وبعد 5 دقائق من عدم التغيير ولم يتم إيقاف نشاط وحدة المعالجة المركزية في العملية.

أنا أستخدم الباندا الإصدار 0.11.0.

أدرك أن هناك مشكلة في الذاكرة في محلل الملفات ، ولكن وفقًا لـhttp://wesmckinney.com/blog/؟p=543يجب إصلاح ذلك.

الملف الذي أحاول قراءته هو 366 ميجابايت ، ويعمل الرمز أعلاه إذا قمت بقص الملف إلى شيء قصير (25 ميجابايت).

لقد حدث أيضًا ظهور رسالة منبثقة تخبرني أنه لا يمكن الكتابة إلى العنوان 0x1e0baf93 ...

تتبع المكدس:

Traceback (most recent call last):
  File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
 <module>
    wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
    return parser.read()
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
    df = DataFrame(col_dict, columns=columns, index=index)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
    dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
    return create_block_manager_from_arrays(arrays, arr_names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
    blocks = form_blocks(arrays, names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
    float_blocks = _multi_blockify(float_items, items)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
    block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
    stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .

قليلا من الخلفية - أحاول إقناع الناس بأن بيثون يمكن أن يفعل الشيء نفسه مثل R. لهذا أحاول تكرار نسخة R التي تعمل

data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)

لا يدير R قراءة الملف أعلاه فقط على ما يرام ، بل يقرأ أيضًا العديد من هذه الملفات في حلقة (ثم يقوم ببعض الأشياء مع البيانات). إذا واجهت Python مشكلة مع ملفات بهذا الحجم ، فقد أقاتل معركة ضائعة ...

75
Anne

الحد من ذاكرة ويندوز

تحدث أخطاء الذاكرة كثيرًا مع بيثون عند استخدام الإصدار 32 بت في Windows. وذلك لأن 32bit يعالج يحصل فقط على 2 غيغابايت من الذاكرة للعب بها بشكل افتراضي.

الحيل لخفض استخدام الذاكرة

إذا كنت لا تستخدم 32bit python في windows ولكنك تتطلع إلى تحسين كفاءة ذاكرتك أثناء قراءة ملفات csv ، فهناك خدعة.

تأخذ الدالة pandas.read_csv خيارًا يسمى dtype. هذا يتيح للباندا معرفة الأنواع الموجودة داخل بيانات ملف CSV.

كيف يعمل هذا

بشكل افتراضي ، ستحاول الباندا تخمين ما يحتوي عليه ملف csv. هذه عملية ثقيلة للغاية لأنه أثناء تحديد نوع dtype ، يجب أن يحتفظ بجميع البيانات الأولية ككائنات (سلاسل) في الذاكرة.

مثال

دعنا نقول CSV الخاص بك يبدو مثل هذا:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01

هذا المثال بالطبع لا يمثل مشكلة في القراءة ، لكنه مجرد مثال.

إذا قرأت الباندا ملف csv أعلاه بدون أي خيار dtype ، فسيتم تخزين العمر كسلسلة في الذاكرة حتى يقرأ الباندا أسطرًا كافية من ملف csv لإجراء تخمين مؤهل.

أعتقد أن الافتراضي في الباندا هو قراءة 1،000،000 صف قبل تخمين نوع dtype.

حل

من خلال تحديد dtype={'age':int} كخيار في .read_csv() ، فسوف يُعلم الباندا أنه يجب تفسير العمر كرقم. هذا يوفر عليك الكثير من الذاكرة.

مشكلة مع البيانات الفاسدة

ومع ذلك ، إذا كان ملف csv تالفًا ، مثل هذا:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01
Dennis, 40+, None-Ur-Bz

بعد ذلك ، يؤدي تحديد dtype={'age':int} إلى كسر الأمر .read_csv() ، لأنه لا يمكن أن يلقي "40+" على int. تعقيم البيانات الخاصة بك بعناية!

هنا يمكنك أن ترى كيف يكون استخدام ذاكرة dataframe لبطاقة الباندا أعلى بكثير عندما يتم حفظ العوامات كسلسلة:

جربه بنفسك

df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 224544 (~224 MB)

df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 79560 (~79 MB)
29
firelynx

واجهت نفس مشكلة الذاكرة مع قراءة بسيطة لملف نصي محدد بعلامات جدولة يبلغ حجمه حوالي 1 جيجابايت (أكثر من 5.5 مليون سجل) وهذا أدى إلى حل مشكلة الذاكرة :

df = pd.read_csv(myfile,sep='\t') # didn't work, memory error
df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds

سبايدر 3.2.3 بيثون 2.7.13 64 بت

3
mooseman

أستخدم Pandas على صندوق Linux الخاص بي ، وواجهت العديد من التسريبات في الذاكرة والتي لم يتم حلها إلا بعد ترقية Pandas إلى أحدث إصدار بعد استنساخها من github.

2
Tarik

لا يوجد خطأ في Pandas 0.12.0 و NumPy 1.8.0.

لقد تمكنت من إنشاء DataFrame كبير وحفظه في ملف CSV ثم قراءته بنجاح. يرجى الاطلاع على المثال هنا . حجم الملف هو 554 ميجا بايت (حتى أنه عمل مع ملف 1.1 جيجا بايت ، استغرق وقتًا أطول ، لتوليد تردد استخدام ملف 1.1 جيجا بايت من 30 ثانية). على الرغم من أن لدي سعة 4 جيجابايت من RAM المتاحة.

اقتراحي هو محاولة تحديث الباندا. الشيء الآخر الذي قد يكون مفيدًا هو محاولة تشغيل البرنامج النصي من سطر الأوامر ، لأنك لا تستخدم Visual Studio (حيث تم اقتراح هذا بالفعل في التعليقات على سؤالك) ، وبالتالي فإنه يحتوي على مزيد من الموارد المتاحة.

2
Oleksandr

لقد واجهت هذه المشكلة أيضًا عندما كنت أعمل في جهاز افتراضي ، أو في مكان آخر حيث تكون الذاكرة محدودة للغاية. لا علاقة له بالباندا أو الفاسدة أو بتنسيق CSV ، ولكنه سيحدث دائمًا إذا حاولت استخدام المزيد من الذاكرة لأنك مغرم باستخدامها ، حتى في بيثون فقط.

الفرصة الوحيدة لديك هي ما جربته بالفعل ، حاول أن تقلل الشيء الكبير إلى قطع أصغر تتناسب مع الذاكرة.

إذا سألت نفسك عن ماهية MapReduce ، فوجدتها بنفسك ... ستحاول MapReduce توزيع القطع على العديد من الأجهزة ، وستحاول معالجة القطعة على جهاز واحد تلو الآخر.

ما اكتشفته مع تسلسل الملفات المقطوعة قد يكون مشكلة بالفعل ، ربما هناك بعض النسخ اللازمة في هذه العملية ... ولكن في النهاية قد يوفر لك ذلك في وضعك الحالي ولكن إذا زاد حجم ملف CSV الخاص بك قليلاً قد تعمل ضد هذا الجدار مرة أخرى ...

يمكن أيضًا أن تكون الباندا ذكية جدًا ، بحيث لا تقوم في الواقع سوى بتحميل مجموعات البيانات الفردية إلى الذاكرة إذا كنت تفعل شيئًا ما ، مثل التسلسل إلى مدافع كبير؟

عدة أشياء يمكنك تجربتها:

  • لا تقم بتحميل جميع البيانات في وقت واحد ، ولكن تقسيمها إلى أجزاء
  • بقدر ما أعرف ، فإن hdf5 قادر على القيام بهذه القطع تلقائيًا ويقوم فقط بتحميل الجزء الذي يعمل عليه البرنامج حاليًا
  • انظر إلى ما إذا كانت الأنواع مقبولة ، فالسلسلة "0.111111" تحتاج إلى ذاكرة أكبر من التعويم
  • ما الذي تحتاجه بالفعل ، إذا كان هناك عنوان كسلسلة ، فقد لا تحتاج إلى تحليل رقمي ...
  • يمكن أن تساعد قاعدة البيانات في الحصول على الأجزاء التي تحتاجها فعليًا وتحميلها فقط (مثل المستخدمين النشطين 1٪ فقط)
1
SebastianNeubauer

على الرغم من أن هذا الحل ليس كحل إصلاح ، إلا أنني أحاول تحويل ملف CSV هذا إلى JSON (يجب أن يكون تافهًا) واستخدام طريقة read_json بدلاً من ذلك - لقد قمت بكتابة وقراءة JSON/dataframes كبيرة الحجم (100s من ميغابايت) في Pandas بهذه الطريقة دون أي مشكلة على الإطلاق.

0
LetMeSOThat4U

جربت chunksize أثناء قراءة ملف CSV الكبير

reader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)

القراءة هي الآن القائمة. يمكننا تكرار reader والكتابة/إلحاق csv الجديد أو القيام بأي عملية

for chunk in reader:
    print(newChunk.columns)
    print("Chunk -> File process")
    with open(destination, 'a') as f:
        newChunk.to_csv(f, header=False,sep='\t',index=False)
        print("Chunk appended to the file")
0
muTheTechie