1

I'm reading a sequence of files and writing them and their parameters in lists, then I want to create a csv which looks like this:

File1 parameterA1 parameterA2
File2 parameterP1 parameterP2 parameterP3

What I get with my code:

file1 parameterA parameterA2
file2 parameterP1 parameterP2 parameterP3

How can I get each parameter in its own cell? Any help appreciated. What's interesting, if I run the code with just 1 file - parameters put in separate cells.

import csv

files = ['f1', 'f2']
params_a = ['a1', 'a2']
params_p = ['p1', 'p2', 'p3']

with open ('csv.csv', 'a') as csvfile:
        csvwriter = csv.writer(csvfile, delimiter = ',')
        for file in files:
            csvfile.write('\n%s\t' % (file) )
            for parameter_a in params_a:
                csvfile.write('%s\t' % (parameter_a))
            for parameter_p in params_p:
                csvfile.write('%s\t' % (parameter_p))

I tried playing with delemeter, other arguments and line endings but it got worse. Not sure what breaks the 'style' for multiple writing operations.

UPD: updated the table to match the code sample

Apollo
  • 31
  • 5
  • 1
    Just to be clear: csvwriter() does not make "cells" and it does not have any features related to "cells". csvwriter() just writes a text file with some formatting, such as numbers separated by commas. Whatever program you use to open that file may or may not display the contents in the way you want. So for a problem like this you need to: A) understand what text file format you want (depends on the program you use to read the file), and then B) configure csvwriter() to create a file with that format. – mhopeng Jan 04 '23 at 21:23
  • 1) What about `'p3'`? 2) Not clear you are assigning the values in `params_a` and `params_p` to `f1` and `f2` as your example output does not use the values in your code. – Adrian Klaver Jan 04 '23 at 22:36
  • @AdrianKlaver My bad, the table didn't match the code, updated it. – Apollo Jan 05 '23 at 07:24
  • @mhopeng yeah thanks, just wanted to describe precisely what I'm looking for, so I wrote about 'cells'. I'm ok with commas, but looks like I'm getting whitespaces between – Apollo Jan 05 '23 at 07:27
  • 2
    csv is a text-based format. Why don't you just provide *text* as your desired output and your current output? The formatting makes it harder to understand than just providing the exact text. – juanpa.arrivillaga Jan 05 '23 at 21:37

3 Answers3

1

To write the CSV from your question you can use next example:

import csv

files = ['f1', 'f2']
params_a = ['a1', 'a2']
params_p = ['p1', 'p2', 'p3']

with open('data.csv', 'w') as f_out:
    writer = csv.writer(f_out)

    # write header
    writer.writerow(['Column A', 'Column B', 'Column C'])

    # write rows
    for f, p1, p2 in zip(files, params_a, params_p):
        writer.writerow([f, p1, p2])

This writes data.csv with following content:

Column A,Column B,Column C
f1,a1,p1
f2,a2,p2
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • And where does `'p3'` go? – Adrian Klaver Jan 04 '23 at 22:37
  • Yeah, there is no `p3` in this example. The code would work if I had an identical set of params for each file, but my case is different. E.g. file1 can have two params and file2 can have one or three. That's why I didn't go with `writerows` – Apollo Jan 05 '23 at 07:17
1

The most straightforward answer based on the code you provided is this:

files = ["f1", "f2"]
params_a = ["a1", "a2"]
params_p = ["p1", "p2", "p3"]

with open("output_manual.csv", "a", newline="") as csvfile:
    csvwriter = csv.writer(csvfile)

    row = [files[0]] + params_a
    csvwriter.writerow(row)

    row = [files[1]] + params_p
    csvwriter.writerow(row)

That outputs:

f1,a1,a2
f2,p1,p2,p3

That params_a belongs to file "f1", and params_p to "f2", seems to be special knowledge you need to manually code.

If your data actually looked like this:

files = [
    "f1",
    "f2",
]

params = [
    ["a1", "a2"],
    ["p1", "p2", "p3"],
]

Then you can do something like this:

with open("output_mine.csv", "w", newline="") as f_out:
    writer = csv.writer(f_out)
    
    for i, file in enumerate(files):
        row = [file] + params[i]
        writer.writerow(row)

You can also dynmaically size a header, if you like:

max_param_len = 0
for param in params:
    if len(param) > max_param_len:
        max_param_len = len(param)

header = ["File"]
for i in range(max_param_len):
    header += [f"Param_{i+1}"]

and then insert it:

...
writer = csv.writer(f_out)
writer.writerow(header)
...

That outputs:

File,Param_1,Param_2,Param_3
f1,a1,a2
f2,p1,p2,p3

Your data could also look like this and something similar will work:

file_param_map = {
    "f1": ["a1", "a2"],
    "f2": ["p1", "p2", "p3"],
}
Zach Young
  • 10,137
  • 4
  • 32
  • 53
  • 1
    Thanks it works! At first I thought writerow won't suit the case, but now I see how it can work for me. – Apollo Jan 09 '23 at 13:52
0
import csv

with open('params_test', 'w') as csv_file:
    files = ['f1', 'f2']
    params_a = ['a1', 'a2']
    params_p = ['p1', 'p2', 'p3']
    # Find the max number of columns needed.
    col_max = max(len(params_a), len(params_p))
    c_writer = csv.writer(csv_file)
    for p in [params_a, params_p]:
        # If number of columns is <  the max number pad with empty strings
        if len(p) < col_max:
             for l in range(col_max - len(p)):
                 p.append('')
    # Add the file name to start of params* list. Then write out row.
    params_a.insert(0, files[0])
    c_writer.writerow(params_a)
    params_p.insert(0, files[1])
    c_writer.writerow(params_p)

cat params_test
f1,a1,a2,
f2,p1,p2,p3


Adrian Klaver
  • 15,886
  • 2
  • 17
  • 28