-1

I want to create a new CSV file with 3 items per row. My source file looks like (there are no new lines / line breaks):

12123, 1324, 232324, 243443, 234, 2345, 2334, 2445, 22355, 222234, 2345

Now I want to transform this file in a CSV file. Take the first three elements and put it in the first row, new line, and take the next three items, etc...

12123, 1324, 232324
24343, 234, 2345
...

How can I do that with Python 3.x? I'm new in Python and don't get it... My previous attempt:

import csv

with open('test.csv') as f:
    reader = csv.reader(f)
    with open('test2.csv', 'w') as csvfile:
        writer = csv.writer(csvfile)
        liste = list(reader)
        print(liste[1:2])

But my list object has only one long item.

Georgy
  • 12,464
  • 7
  • 65
  • 73
Tobias
  • 4,921
  • 4
  • 31
  • 40
  • 4
    There are multiple problems here, solve one at a time: (1) How to read a CSV (2) How to take the first three elements of a list (3) How to write a CSV. Try solving each one by itself. You don't even need to involve any files or anything CSV related to solve (2). – Alex Hall Dec 26 '16 at 22:55
  • 1
    `liste` is a list of lists: each inner list is a line of the file. You need to iterate over `liste` and get the first three objects of each of the sublists. – Alex Hall Dec 26 '16 at 23:09
  • Possible duplicate of [How to print several array elements per line to text file](https://stackoverflow.com/questions/14941854/how-to-print-several-array-elements-per-line-to-text-file) – Georgy Nov 29 '19 at 11:45

7 Answers7

1

You mentioned:

My source file looks like (there are no new lines / line breaks):

12123, 1324, 232324, 243443, 234, 2345 2334, 2445, 22355, 222234, 2345

So this reads one long row of a CSV, then writes it as groups of three per line:

import csv

with open('test.csv',newline='') as f:
    reader = csv.reader(f)
    line = next(reader) # Read the one long line

with open('test2.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    for i in range(0,len(line),3): # step by threes.
        writer.writerow(line[i:i+3])

Note that correct use of the csv module requires the files to be opened with newline='' in Python 3 ('rb' or 'wb' in Python 2).

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
0

File I/O neutral solution:

csv = """12123, 1324, 232324, 243443, 234, 2345

2334, 2445, 22355, 222234, 2345"""  # replace this with the file you read from CSV

def sixPerLineToThreePerLine(s):
  result = ""
  for line in s.split("\n"):
    sp = line.split(", ")
    result = result + ", ".join(sp[:3]) + "\n" + ", ".join(sp[3:])
  return result

print(sixPerLineToThreePerLine(csv))  # replace this with code to write to CSV
0

This should help. This was written using python 2.7 so if you have any problems running it in 3.x let me know and I can try to help.

import csv # import the csv module you will need, if you want to avoid this you can just read it in as a text file
output = """""" # make an output string
num = 0 #initialize num that trakcs how many numbers have ben read
with open('datacsv.csv', 'rb') as f: # open the input file
    file = csv.reader(f) # initialize the file as being a csv file
    for row in file: # for every row (you said no new lines, but just in case)
        for data in row: # for ever entry in the row
            if(num == 2): # if you have read in three numbers
                num = 0 # reset num
                output += data + "\n" # output a new line and the current number
            else:
                num += 1 # increment num
                output += data + "," # add to output the data and a comma


new = open("outputcsv.csv", "w") # create the output file
new.write(output) # write the output data to the new file
Wso
  • 192
  • 2
  • 11
0

Here's a solution but it's a bit long. Basically I would write all the values in the csv to a list, then remove three value from the list and write to the csv until there's no values left.

import csv

# just an example csv
with open('example.csv', 'w') as csvfile:
    # create example csv with a single row of numbers 0-19
    spamwriter = csv.writer(csvfile)
    spamwriter.writerow([i for i in range(20)])

# open file for reading, append values to list
l = []
with open('example.csv') as csvfile:
    # read the example file into a list
    reader = csv.reader(csvfile)
    for row in reader:
        for val in row:
            l.append(val)


# write to the original file with 3 values per line
with open('example.csv', 'w') as csvfile:
    spamwriter = csv.writer(csvfile)
    while l:
        try:
            # write to file 3 values at a time
            spamwriter.writerow(l[:3])
            l = l[3:]
        except:
            # add last bit of file, if file doesn't devide evenly by 3
            spamwriter.writerow(l)
            break

I'd recommend checking out Pandas I find it a lot easier to manipulate csvs with it, but it's not in the standard library.

ConorSheehan1
  • 1,640
  • 1
  • 18
  • 30
0

What you want to do is read in the data from the file, then split it into individual elements. Once you have it in individual elements you can put them in groups of three and write to your output file.

Something like this should work:

def read_data(file_path):
    with open(file_path, 'r') as fh:
        elements = fh.read()
    data = [element.strip() for element in elements.split(',')]
    return data

def group(data):
    grouped = [', '.join(data[n:n+3]) for n in range(0, len(data), 3)]
    return grouped

def write(data, output):
    with open(output, 'w') as fh:
        fh.writelines(data)

def main():
    data = read('test.csv')
    data = group(data)
    write(data, 'test2.csv')
Batman
  • 8,571
  • 7
  • 41
  • 80
0

I wrote a short program that I think does what you wanted:

It reads all lines from the reader file and then just insert them into the writer file 3 by 3 :)

import csv

def main():

    with open('ex.csv', 'rb') as f:
    reader = csv.reader(f)
    with open('ex2.csv', 'wb') as csvfile:
        writer = csv.writer(csvfile)
        pass_on = []

        for row in reader:
            #print row

            for c in xrange(0, len(row)): # passing on objects after count of 3
                if row[c]:
                    pass_on.append(row[c])


        print pass_on

        while pass_on:

            writer.writerow(pass_on[:3])
            pass_on = pass_on[3:]



    print "done"

if __name__ == '__main__':
    main()
Ofer Arial
  • 1,129
  • 1
  • 10
  • 25
0

A four-line solution without the csv module:

with open('oneline_numbers.csv') as fobj_in, open('three_numbers.csv', 'w') as fobj_out:
    numbers = iter(entry.strip() for entry in next((fobj_in)).split(','))
    for line in zip(*[numbers] * 3):
        fobj_out.write(', '.join(line) + '\n')
Mike Müller
  • 82,630
  • 20
  • 166
  • 161