1

I have an input file, in which I am making an string replace operation.

I read the file cell by cell, replace the string and then write it back to a new CSV file.

input_file = open('/Users/tcssig/Desktop/unstacked2.csv', 'r', encoding='utf-8')
output_file = open('/Users/tcssig/Desktop/unstacked3.csv', 'w', encoding='utf-8')
writer = csv.writer(output_file , delimiter=' ')
reader = csv.reader(input_file)
for row in reader:
    for string in row:
       data = [string.replace('read','write')]
       print(data)
       writer.writerow(data)

Above code runs well, but I get an empty output file.

Example of data :

    reading reading reading reading
interval        0   1   2   3

who axis


Mikael  X   0   10  20  30

Mikael  Y   50  40  30  20

Mikael  Z   100 90  80  70

Mike    X   0   0.1 0.2 0.3

Mike    Y   0.5 0.4 0.3 0.2

Mike Z 1 0.9 0.8 0.7

What am i missing?

Sarang Manjrekar
  • 1,839
  • 5
  • 31
  • 61
  • Correct the indentation; it's not clear what code falls into the `for string in row:` block. Also, to be clear, are you trying to convert each cell to a separate row, or just replace the values in the cells? – ShadowRanger Sep 23 '16 at 04:30
  • Consider using [`with`](https://docs.python.org/2/reference/compound_stmts.html#the-with-statement) statement(s) to have your files closed automatically. – martineau Sep 23 '16 at 04:31
  • @scott, added the data example above – Sarang Manjrekar Sep 23 '16 at 06:49

2 Answers2

2

Close your files:

output_file.close()
input_file.close()

Also see this answer regarding use of context managers https://stackoverflow.com/a/441446/4663466

Community
  • 1
  • 1
Scott
  • 6,089
  • 4
  • 34
  • 51
  • Thanks Scott, I am able to get the output now, but all in one CSV column. Is there any way, I can preserver my input file structure ? – Sarang Manjrekar Sep 23 '16 at 04:52
  • See the comment under your question - the line `writer.writerow(data)` is indented incorrectly. – Tim Pietzcker Sep 23 '16 at 05:26
  • @Sarang your nested loop is iterating a row in your csv, then through each string replacing 'read' with 'write'. If you have a question about how to edit line by line you should ask a new question. It would be helpful to have an example of your data, if possible, because str.replace() may not be your only option to edit the output. – Scott Sep 23 '16 at 05:29
  • @scott, added the data example above – Sarang Manjrekar Sep 23 '16 at 06:50
  • @Sarang as Dinesh Pundkar points out if your data is not actually a csv it is easier to edit each line as a whole. Dinesh's answer at the bottom does what you are asking for, but you can skip `.replace(","," ")` since your file is not actually comma separated. – Scott Sep 23 '16 at 15:33
1

Content of input file:

"Roll No" English read Science
"Roll No" English Write Science

Problem with your code:

  1. As mentioned by @Scott, files are not closed.
  2. Your are reading cell by for string in row: and replacing string there. But after replacement you are writing that cell as row in your file. For example, output file with your code looks file :

    Roll No

    English

    read

    Science

This is due to above mentioned reason i.e. you are writing each cell.

How to make it working?

Comments inline with code

import csv
input_file = open('mark.csv', 'r', encoding='utf-8')
output_file = open('result.csv', 'w')
writer = csv.writer(output_file , delimiter=' ', encoding='utf-8')
reader = csv.reader(input_file)
for row in reader:
    #Initailize empty list for each row
    data = []
    for string in row:
       #Replace and add to data list
       data.append(string.replace('read','write'))
    #Now write complete
    writer.writerow(data)

input_file.close()
output_file.close()

Output:

"Roll No" English write Science

"Roll No" English Write Science

You can achieve same thing without csv module.

with open("mark.csv") as input_file:
    with open("result.csv",'w') as output_file:
        for line in input_file:
            new_line = (line.replace("read","write")).replace(","," ")
            output_file.write(new_line)
Dinesh Pundkar
  • 4,160
  • 1
  • 23
  • 37