简体   繁体   中英

How to split a CSV file on blank rows

I have a CSV file which starts a new subject after two blank rows. I want to split this file into two different files. How can I do that?

................
................                
Biology I               
BGS Shivamogga I PUC    Exam Results            
Student Exam    # Questions Correct Answers Score %
ADARSHGOUDA M MUDIGOUDAR    Biology I - Chapter 1   35  23  65.70%
ADARSHGOUDA M MUDIGOUDAR    Biology I - Chapter 1   35  29  82.90%
ADARSHGOUDA M MUDIGOUDAR    Biology I - Chapter 1   35  32  91.40%
.
.
.
.

................
................                
Chemistry I             
BGS Shivamogga I PUC    Exam Results            
Student Exam    # Questions Correct Answers Score %
AISHWARYA P Chemistry I - Chapter 1 29  20  69.00%
MAHARUDRASWAMY M S  Chemistry I - Chapter 1 29  14  48.30%
NIKHIL B    Chemistry I - Chapter 1 29  20  69.00%

I have tried using dropnas and skiprows to split the dataframe, but I don't want to hard-code the number of rows. I want to split based on those first two blank rows.

I would do something along the lines of this:

with open('input.txt','r') as input_file:
    data_str = input_file.read()
    data_array = data_str.split('\n\n') # Split on all instances of double new lines
    for i, smaller_data in enumerate(data_array):   
        with open(f'new_file_{i}.txt','w') as new_data_file:
            new_data_file.write(smaller_data)

I'd just use the csv module, coping rows across from a csv.reader() to a csv.writer() object, and keeping a count of consecutive blank rows as you go along. Every time you find multiple blank rows replace the write object with one for a new file.

You can detect empty rows with the any() function , as a blank row will consist of just empty strings or no values at all:

isblank = not any(row)

Presuming that numbered files in the same directory would suffice, this should work:

import csv
from pathlib import Path

def gen_outputfiles(outputdir, basefilename):
    """Generate open files ready for CSV writing, in outputdir using basefilename

    Numbers are inserted between the basefilename stem and suffix; e.g.
    foobar.csv becomes foobar001.csv, foobar002.csv, etc.

    """
    outputbase = Path(basefilename)
    outputstem, outputsuffix = outputbase.stem, outpubase.suffix
    counter = 0
    while True:
        counter += 1
        yield outputdir / f'{outputstem}{counter:03d}{outputsuffix}'.open(mode='w', newline='')

def split_csv_on_doubleblanks(inputfilename, basefilename=None, **kwargs):
    """Copy CSV rows from inputfilename to numbered files based on basefilename

    A new numbered target file is created after 2 or more blank rows have been
    read from the input CSV file.

    """
    inputpath = Path(inputfilename)
    outputfiles = gen_outputfiles(inputpath.parent, basefilename or inputpath.name)

    with inputpath.open(newline='') as inputfile:
        reader = csv.reader(inputfile, **kwargs)
        outputfile = next(outputfiles())
        writer = csv.writer(outputfile, **kwargs)
        blanks = 0
        try:
            for row in reader:
                isblank = not any(row)
                if not isblank and blank > 1:
                    # skipped more than one blank row before finding a non-blank
                    # row. Open a new output file
                    outputfile.close()
                    outputfile = next(outputfile)
                    writer = csv.writer(outputfile, **kwargs)
                blank = blank + 1 if isblank else 0
                writer.writerow(row)
        finally:
            if not outputfile.closed:
                outputfile.close()

Note that I copy across the blank rows too, so your files do end up with multiple blank rows. That can be remedied by replacing the blanks counter with a list of blank rows to write out to the writer object whenever you want to reset the counter and there was only a single element in that list. That way single blank rows would be preserved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM