0

I have a CSV with a bunch of data, and I need to change the data in a specific row and column. I'm able to read through the file, find the row,col that I need to change, change the data, but I can't figure out how to commit that change to memory and re-write the CSV correctly.

The following code does not fail, however it is not correct. Instead of committing the changes that I make to the column (col), it just duplicates the row that I want to change. The data is unchanged, and now I just have duplicate rows where I wanted changes.

import csv
import re
from tempfile import NamedTemporaryFile
import shutil

csvName = raw_input("Enter the filename: ")
tempfile = NamedTemporaryFile(delete=False)
newSize = 0
newArea = 0

with open(csvName, 'rb') as readCSV, tempfile:
    reader = csv.reader(readCSV)
    writer = csv.writer(tempfile)
    for row in reader:
        for col in row:
            if col.startswith('Connection:'):
                print col
            if col.startswith('Size:'):
                print "Current", col
                newSize = raw_input("Enter new size: ")
                newArea = int(newSize)*int(newSize)
                col = re.sub('[0-9]+', newSize, col)
                writer.writerow(row)
            if col.startswith('Area:'):
                col = re.sub('[0-9]+', str(newArea), col)
                writer.writerow(row)
        writer.writerow(row)

shutil.move(tempfile.name, csvName)

This is an example of one bit of data that needs to be changed:

Connection: D14Conn Type: B2B Size: 140 Geometry: Square Area: 19600

My code above will simply duplicate new rows into this data, and the changes I make to col are not committed - as below

Connection: D14Conn Type: B2B Size: 140 Size: 140 Geometry: Square Area: 19600 Area: 19600

2 Answers 2

1

When you assign to col you are assigning to a copy of the col value in row. As you iterate through row, you need to either keep reference to the index of the value you want to change, and update row at that index so that when you call writer.writerow(row) you are actually writing with a changed object, or create a new_row with the desired columns. As for your duplicates, remove writer.writerow(row) calls from your if blocks, they are redundant.

Sign up to request clarification or add additional context in comments.

5 Comments

I figured that this is what I needed to do. So, I just need to keep track of which row number I've iterated to, and then which column number I've iterated to, and then change the value at that row/col, right?
reader is an iterable object, so you will not necessarily benefit from tracking the row number, but you do not need to as each row will simply be an array of values. So if the 3rd column in the row you're looking at should be updated simply say row[2]= ___ and then your writer.writerow(row) will reflect the update
So I understand your answer, but now I'm having trouble with execution. It doesn't seem that csvReader keeps track of the csv in Row:Column format. When I try the following code while keeping track of iterations, I just end up with a "list index out of range" error which I assume is because of my attempt to refer to column number:
row[rowNum][colNum] = re.sub('[0-9]+', newSize, col)
No problem dude! Brush up on iterator objects in Python. They aren't indexed, they simply implement __iter__() and next() functions, which is usable in a statement with in such as your for row in reader
0

Your row isn't changed. You need to make a new_row with your new column values and do writer.writerow(new_row)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.