ฉันจะกรองบรรทัดเมื่อโหลดในฟังก์ชัน Pandas read_csv ได้อย่างไร


105

ฉันจะกรองบรรทัดของ CSV ที่จะโหลดลงในหน่วยความจำโดยใช้แพนด้าได้อย่างไร ดูเหมือนว่าเป็นตัวเลือกที่ควรหาread_csvนี้ดูเหมือนว่าตัวเลือกที่หนึ่งควรหาในฉันพลาดอะไรไปรึเปล่า?

ตัวอย่าง: เรามี CSV พร้อมคอลัมน์การประทับเวลาและเราต้องการโหลดเฉพาะบรรทัดที่มีการประทับเวลามากกว่าค่าคงที่ที่กำหนด

คำตอบ:


179

ไม่มีตัวเลือกในการกรองแถวก่อนโหลดไฟล์ CSV ลงในวัตถุแพนด้า

คุณสามารถโหลดไฟล์แล้วกรองโดยใช้df[df['field'] > constant]หรือหากคุณมีไฟล์ขนาดใหญ่มากและคุณกังวลว่าหน่วยความจำจะหมดให้ใช้ตัววนซ้ำและใช้ตัวกรองเมื่อคุณเชื่อมต่อส่วนต่างๆของไฟล์เช่น:

import pandas as pd
iter_csv = pd.read_csv('file.csv', iterator=True, chunksize=1000)
df = pd.concat([chunk[chunk['field'] > constant] for chunk in iter_csv])

คุณสามารถปรับเปลี่ยนchunksizeให้เหมาะสมกับหน่วยความจำที่คุณมีได้ ดูที่นี่สำหรับรายละเอียดเพิ่มเติม


สำหรับchunk['filed']>constantฉันสามารถ sandwich มันระหว่าง 2 ค่าคงที่? เช่น: constant1> chunk ['field']> constant2. หรือใช้ 'in range' ได้?
weefwefwqg3

1
ลอง:chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
Johannes Wachs

สิ่งนี้หายไป.locหรือไม่? chunk.loc[chunk['field'] > constant]
Vincent

1
คุณสามารถใช้บูลีนมาสก์โดยมีหรือไม่มี.locก็ได้ ฉันไม่คิดว่าจะ.locมีอยู่ในปี 2012 แต่ฉันคิดว่าทุกวันนี้การใช้.locงานค่อนข้างชัดเจน
Matti John

10

read_csvผมไม่ได้หาวิธีที่ตรงไปข้างหน้าจะทำมันในบริบทของ อย่างไรก็ตามread_csvส่งคืน DataFrame ซึ่งสามารถกรองได้โดยการเลือกแถวตามเวกเตอร์บูลีนdf[bool_vec]:

filtered = df[(df['timestamp'] > targettime)]

นี่คือการเลือกแถวทั้งหมดใน df (สมมติว่า df เป็น DataFrame ใด ๆ เช่นผลลัพธ์ของการread_csvโทรซึ่งอย่างน้อยก็มีคอลัมน์วันที่และเวลาtimestamp) ซึ่งค่าในtimestampคอลัมน์นั้นมากกว่าค่าของ targettime คำถามที่คล้ายกัน


1
ฉันไม่แน่ใจเกี่ยวกับเรื่องนี้ แต่ฉันรู้สึกว่ามันจะหนักมากสำหรับการใช้งานหน่วยความจำ
Nathan

3

หากช่วงที่กรองอยู่ติดกัน (ตามปกติแล้วจะเป็นตัวกรองเวลา (ตราประทับ)) วิธีแก้ปัญหาที่เร็วที่สุดคือการฮาร์ดโค้ดช่วงของแถว เพียงรวมskiprows=range(1, start_row)กับnrows=end_rowพารามิเตอร์ จากนั้นการนำเข้าจะใช้เวลาไม่กี่วินาทีซึ่งโซลูชันที่ยอมรับจะใช้เวลาไม่กี่นาที การทดลองเพียงไม่กี่ครั้งในครั้งแรกstart_rowไม่ใช่ต้นทุนที่มากเนื่องจากประหยัดเวลาในการนำเข้า range(1,..)ขอให้สังเกตเราเก็บไว้แถวส่วนหัวโดยใช้


0

อีกทางเลือกหนึ่งสำหรับคำตอบที่ยอมรับคือการใช้ read_csv () กับ StringIO ซึ่งได้มาจากการกรองไฟล์อินพุต

with open(<file>) as f:
    text = "\n".join([line for line in f if <condition>])

df = pd.read_csv(StringIO(text))

วิธีแก้ปัญหานี้มักจะเร็วกว่าคำตอบที่ยอมรับเมื่อเงื่อนไขการกรองยังคงรักษาเส้นไว้เพียงเล็กน้อย


-3

หากคุณใช้ linux คุณสามารถใช้ grep

# to import either on Python2 or Python3
import pandas as pd
from time import time # not needed just for timing
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def zgrep_data(f, string):
    '''grep multiple items f is filepath, string is what you are filtering for'''

    grep = 'grep' # change to zgrep for gzipped files
    print('{} for {} from {}'.format(grep,string,f))
    start_time = time()
    if string == '':
        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)
        data = pd.read_csv(grep_data, sep=',', header=0)

    else:
        # read only the first row to get the columns. May need to change depending on 
        # how the data is stored
        columns = pd.read_csv(f, sep=',', nrows=1, header=None).values.tolist()[0]    

        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)

        data = pd.read_csv(grep_data, sep=',', names=columns, header=None)

    print('{} finished for {} - {} seconds'.format(grep,f,time()-start_time))
    return data

1
การใช้ grep เป็นทางเลือกที่ไม่ดีอย่างมากด้วยเหตุผลหลายประการ 1) มันช้า 2) มันไม่สามารถพกพาได้ 3) มันไม่ใช่แพนด้าหรืองูหลาม (คุณสามารถใช้นิพจน์ทั่วไปได้ใน python) ซึ่งเป็นสาเหตุที่ฉันลดคะแนนคำตอบของคุณ
Ahmed Masud

โซลูชันของคุณใช้ไม่ได้กับทุกแพลตฟอร์มและรวมถึง Grep ด้วย นี่คือเหตุผลของการโหวตลด
Roman Orac

-3

คุณสามารถระบุnrowsพารามิเตอร์

import pandas as pd df = pd.read_csv('file.csv', nrows=100)

รหัสนี้ทำงานได้ดีในเวอร์ชัน 0.20.3


1
OP กำลังถามวิธีกรองไม่ จำกัด จำนวนบรรทัดที่อ่าน นี่คือเหตุผลที่ฉันลดคะแนนคำตอบของคุณ
Roman Orac
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.