1

So, I have a python tuple. I am trying to write it to a CSV file. What I did so far I am able to write to the CSV but all my data appears in one row. Can anyone tell me how can I convert it into columns ? For example this is the data in one row on my CSV.

100 0.01 11139155 5569534 0.499996 NO SYNC 555 0.01 2306110 1153050 0.499998 NO SYNC 333 0.22 3434535 4446466 0.453535 NO SYNC

What I want to do I want to organize this tuple in a way that after each NO SYNC it moves to the next row.

100 0.01 11139155 5569534 0.499996 NO SYNC
555 0.01 2306110 1153050 0.499998 NO SYNC
333 0.22 3434535 4446466 0.453535 NO SYNC

This is my script

with open ('File path') as f:
     writer = csv.writer(f, delimiter = ',')
     writer.writerow(results_t1)
f.close()

Where results_t1 is my input tuple.

My input tuple looks like this :

(100, 0.01, 11139155, 5569534, 0.499996094856387, 'NO SYNC', 555, 0.01, 2306110, 1153050, 0.499997831846703, 'NO SYNC', 3081, 0.01, 1951735, 975863, 0.499997694359122, 'NO SYNC', 17100, 0.01, 2896740, 1448360, 0.499996547843438, 'NO SYNC', 94912, 0.01, 1800105, 900045, 0.499995833576375, 'NO SYNC', 526805, 0.01, 2290245, 1145113, 0.499995851972169, 'NO SYNC', 2924018, 0.01, 2256745, 1128371, 0.499999335325879, 'NO SYNC', 16229682, 0.01, 2004625, 1002304, 0.49999575980545, 'NO SYNC', 90082412, 0.01, 1912945, 956468, 0.499997647606178, 'NO SYNC', 500000000, 0.01, 1421040, 710518, 0.499998592580082, 'NO SYNC')

Rahul Chawla
  • 1,048
  • 10
  • 15
Omar
  • 21
  • 3

3 Answers3

2

Assuming constant number of columns in CSV (Which usually is the case). And using chunk breaker got from a highly coveted answer here

d = (100, 0.01, 11139155, 5569534, 0.499996094856387, 'NO SYNC', 555, 0.01, 2306110, 1153050, 0.499997831846703, 'NO SYNC', 3081, 0.01, 1951735, 975863, 0.499997694359122, 'NO SYNC', 17100, 0.01, 2896740, 1448360, 0.499996547843438, 'NO SYNC', 94912, 0.01, 1800105, 900045, 0.499995833576375, 'NO SYNC', 526805, 0.01, 2290245, 1145113, 0.499995851972169, 'NO SYNC', 2924018, 0.01, 2256745, 1128371, 0.499999335325879, 'NO SYNC', 16229682, 0.01, 2004625, 1002304, 0.49999575980545, 'NO SYNC', 90082412, 0.01, 1912945, 956468, 0.499997647606178, 'NO SYNC', 500000000, 0.01, 1421040, 710518, 0.499998592580082, 'NO SYNC')

# 6 columns in a row
chunks = [d[i:i + 6] for i in range(0, len(d), 6)]

with open ('File path', 'w') as f:
     writer = csv.writer(f, delimiter = ',')
     writer.writerows(d)
Rahul Chawla
  • 1,048
  • 10
  • 15
  • i think you need to add `with open ('File path', 'w) as f:` – rs311 Nov 14 '18 at 16:41
  • I am trying your technique but it is giving me error. So, NO SYNC is a string as you can see in my updated post. It is giving me an error 'tuple' object has no attribute 'replace'. Also, can you please tell me why youre using a $ sign ? – Omar Nov 14 '18 at 16:51
  • @rs311 Thanks for pointing that out, edited the answer now. Omar, added the explanation in answer itself. – Rahul Chawla Nov 16 '18 at 08:17
0

Here's a quick example of one way you might approach this.

>>> data = "1 2 3 4 5 6 7 8 9 10"
>>> items = data.split(" ")
>>> chunk_size = 5
>>> chunks = [items[i:i+chunk_size] for i in range(len(items)/chunk_size)]
>>> chunks
[['1', '2', '3', '4', '5'], ['2', '3', '4', '5', '6']]
>>> "\n".join([" ".join(chunk) for chunk in chunks])
'1 2 3 4 5\n2 3 4 5 6'

Note that there are some unsafe assumptions here. For example, I'm assuming that your lines are of a consistent length which you know at the start.

If your lines are not of a known consistent length, and you want to break on a particular token, here's how you might do that:

>>> data = "1 2 3 4 STOP 5 6 7 8 STOP"
>>> token = "STOP"
>>> chunks = data.split(token)
>>> "\n".join(["{} {}".format(chunk, token) for chunk in chunks])
'1 2 3 4  STOP\n 5 6 7 8  STOP\n STOP'
>>> 

Obviously, once you have the data rows you can simply emit them to a file.

Jon Kiparsky
  • 7,499
  • 2
  • 23
  • 38
0

I may have gone a little overboard on the solution here, but the below will provide you the output you're looking to achieve.

This should provide a re-usable function for the future in case you have another problem similar to this which forces you to find something other than 'NO SYNC'.

Like @Rahul Chawla's answer, this looks for your new line identifier NO SYNC and updates it to be NOSYNC!. The reason this is helpful is that it gives us a way to create a list of entries ending with NO SYNC by splitting a string every time we see !. You can customize what delimiter (delim paramter, default is !) gets appended to your find parameter based on what is not present in your data.

import csv

raw_data = (
100, 0.01, 11139155, 5569534, 0.499996094856387, 'NO SYNC', 555, 0.01, 2306110, 1153050, 0.499997831846703, 'NO SYNC',
3081, 0.01, 1951735, 975863, 0.499997694359122, 'NO SYNC', 17100, 0.01, 2896740, 1448360, 0.499996547843438, 'NO SYNC',
94912, 0.01, 1800105, 900045, 0.499995833576375, 'NO SYNC', 526805, 0.01, 2290245, 1145113, 0.499995851972169,
'NO SYNC', 2924018, 0.01, 2256745, 1128371, 0.499999335325879, 'NO SYNC', 16229682, 0.01, 2004625, 1002304,
0.49999575980545, 'NO SYNC', 90082412, 0.01, 1912945, 956468, 0.499997647606178, 'NO SYNC', 500000000, 0.01, 1421040,
710518, 0.499998592580082, 'NO SYNC')


def identify_new_rows(data, find, delim='!'):
    """convert a flat tuple/list, or string into a list of lists given something to `find`."""
    if isinstance(data, tuple):
        data = " ".join(map(str, data))
    elif isinstance(data, list):
        data = " ".join(data)
    data = [[x for x in d.split(' ') if str(x) != ''] for d in data.replace(find, str(find).replace(' ', '') + delim).split(delim) if len(d) > 0]
    return data



with open(r'~/path/to/your/file.csv', 'w', newline='') as myfile:
    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL, delimiter=',')
    wr.writerows(identify_new_rows(raw_data, 'NO SYNC'))

I will note there are flaws in this approach when attempting to apply to other data sets, as this presumes there are no strings with spaces in your data (other than the current delimiter - which gets handled in the list comprehension.

rs311
  • 353
  • 1
  • 2
  • 12