Modify a table in .txt file using python

Question:

I have a .txt file containing a set of data organized as follow:

(id1) (name1) (x coordinate1) (y coordinate1) (value1)
(id2) (name2) (x coordinate2) (y coordinate2) (value2) 
(id3) (name3) (x coordinate3) (y coordinate3) (value3) 

..... 

Now I want to move all (names) from column 2 to column 4. The code I wrote is this:

with open("C:\path\to\input\file.txt","r") as f:
    rows = list(f)
    table = [["."],["."],["."],["."],["."],["."]]*len(rows)
    for i in range(len(rows)):
        row = rows[i].split(" ")
        table[6*i] = row[0]+" "
        table[6*i+1] = row[2]+" "
        table[6*i+2] = row[3]+" "
        table[6*i+3] = row[1]+" "
        table[6*i+4] = row[4]
        table[6*i+5] = "n"
    with open("C:\path\to\output\file.txt","w") as o:
        o.writelines(table)

it performs the task but the output contains a blank line after each row. I have tried hours to get rid of them but I cannot figure out how to get a correct output. The wrong output is this:

(id1) (x coordinate1) (y coordinate1) (name1) (value1)

(id2) (x coordinate2) (y coordinate2) (name2) (value2) 

(id3) (x coordinate3) (y coordinate3) (name3) (value3) 

..... 
Asked By: Alessandro

||

Answers:

You are adding a line break, try removing this line:

table[6*i+5] = "n"

Since the file you are pulling in has line breaks they get automatically included with the last item in your list.

Edit:
Your source file might be a little wonky, you can also change that last line to be:

table[6*i+5] = ""

Answered By: sniperd

When you read the data from the file, the new lines are present in the data, hence, when you write manipulate and then rewrite the data in another file, it automatically the new lines. Hence there is no need to manually add the new lines yourself since that will just add extra unnecessary new lines(which is the problem we are facing).

So you must remove this line –table[6*i+5] = "n". I hope this fixes your problem.

Answered By: Ved Rathi

As already noted, you are adding a line break to each line, but your column 4 already contains a line break, resulting in 2 breaks.

However there is another problem with your code. file.writelines expects a list of strings, usually with a line break at the end of each. But you create a table which is instead a long list of lists, each containing 1 string:

table = [["."],["."],["."],["."],["."],["."]]*len(rows)

You then replace these sub-lists, one by one, with strings:

table[6*i] = row[0]+" "   # etc.

If any are not replaced, writelines will raise an error because there is a list where it expects a string. So you need to make some additional adjustments to make your existing code work:

with open("input.txt") as f:
    rows = list(f)
table = ["", "", "", "", ""]*len(rows)
for i in range(len(rows)):
    row = rows[i].split(" ")
    table[5*i] = row[0]+" "
    table[5*i+1] = row[2]+" "
    table[5*i+2] = row[3]+" "
    table[5*i+3] = row[1]+" "
    table[5*i+4] = row[4]
with open("output.txt","w") as o:
    o.writelines(table)

However a better way of doing this would be to build the table one row at a time, like this:

with open("input.txt") as f:
    table = []
    for row in f:
        row = row.strip().split(" ")  # strip removes any line breaks / extra spaces
        table.append([row[0], row[2], row[3], row[1], row[4]])

with open("output.txt","w") as o:
    o.writelines(" ".join(row) + "n" for row in table)

Better still, use the csv module which is designed for this and will deal with the newlines automatically:

import csv
with open("input.txt") as in_file, open("output.txt", "w", newline="") as out_file:
    writer = csv.writer(out_file, delimiter=" ")
    for row in csv.reader(in_file, delimiter=" "):
        writer.writerow([row[0], row[2], row[3], row[1], row[4]])

or pandas:

import pandas as pd
pd.read_csv("input.txt", sep=" ", header=None)[[0, 2, 3, 1, 4]] 
    .to_csv("output.txt", sep=" ", header=False, index=False)
Answered By: Stuart

Pitty you are required to use Python. You could do it command line (assuming your data is a in a file data.txt):

sed -e 's/) (/);(/g' data.txt | awk -F ";" '{print $1 ";" $3 ";" $4 ";" $5 ";" $2}' | sed -e 's/;/ /g'
Answered By: Bart Barnard
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.