I have a text file with multiple matrices like this:
4 5 1
4 1 5
1 2 3
[space]
4 8 9
7 5 6
7 4 5
[space]
2 1 3
5 8 9
4 5 6
I want to read this input file in python and store it in multiple matrices like:
matrixA = [...] # first matrix
matrixB = [...] # second matrix
so on. I know how to read external files in python but don't know how to divide this input file in multiple matrices, how can I do this?
Thank you
You can write a code like this:
all_matrices = [] # hold matrixA, matrixB, ...
matrix = [] # hold current matrix
with open('file.txt', 'r') as f:
values = line.split()
if values: # if line contains numbers
matrix.append(values)
else: # if line contains nothing then add matrix to all_matrices
all_matrices.append(matrix)
matrix = []
# do what every you want with all_matrices ...
I am sure the algorithm could be optimized somewhere, but the answer I found is quite simple:
file = open('matrix_list.txt').read() #Open the File
matrix_list = file.split("\n\n") #Split the file in a list of Matrices
for i, m in enumerate(matrix_list):
matrix_list[i]=m.split("\n") #Split the row of each matrix
for j, r in enumerate(matrix_list[i]):
matrix_list[i][j] = r.split() #Split the value of each row
This will result in the following format:
[[['4', '5', '1'], ['4', '1', '5'], ['1', '2', '3']], [['4', '8', '9'], ['7', '5', '6'], ['7', '4', '5']], [['2', '1', '3'], ['5', '8', '9'], ['4', '5', '6']]]
Example on how to use the list:
print(matrix_list) #prints all matrices
print(matrix_list[0]) #prints the first matrix
print(matrix_list[0][1]) #prints the second row of the first matrix
print(matrix_list[0][1][2]) #prints the value from the second row and third column of the first matrix
Related
I have a string of 1s and 0s that I need to insert into a [4] by [4] matrix, that I can then use for other things.
This is my attempt at it:
b = '0110000101101000'
m = [[], [], [], []]
for i in range(4):
for j in range(4):
m[i].append(b[i * j])
But where I expected to get
[['0', '1', '1', '0'], ['0', '0', '0', '1'], ['0', '1', '1', '0'], ['1', '0', '0', '0']
I got [['0', '0', '0', '0'], ['0', '1', '1', '0'], ['0', '1', '0', '0'], ['0', '0', '0', '1']].
Could someone point me in the right direction here?
Get paper and a pencil and write a table of what you have now vs what you want:
i j i*j desired
0 0 0 0
0 1 0 1
0 2 0 2
0 3 0 3
1 0 0 4
1 1 1 5
... up to i=3, j=3
Now you can see that i * j is not the correct index in b. Can you see what the desired index formula is?
I'd agree with #John Zwinck that you can easily figure it out but if you hate math simply do
counter = 0
for i in range(4):
for j in range(4):
m[i].append(b[counter])
counter += 1 # keep track of the overall iterations
otherwise you have to find the starting row you are in (i * columns) and add the current column index
m[i].append(b[i * 4 + j]) # i * 4 gives the overall index of the 0th element of the current row
Here is a hint: range(4) starts from 0 and ends at 3.
See the python documentation: https://docs.python.org/3.9/library/stdtypes.html#typesseq
First of all, the rule to convert coordinates to index is index = row * NRO_COLS + col. You should use i * 4 + j.
Second, you can use list comprehension:
m = [[b[i * 4 + j] for j in range(4)] for i in range(4)]
then, it can be rewritten as:
m = [[b[i + j] for j in range(4)] for i in range(0, len(b), 4)]
or
m = [list(b[i:i+4]) for i in range(0, len(b), 4)]
another alternative is to use numpy, which is a great library, specially to handle multidimensional arrays
import numpy as np
m = np.array(list(b)).reshape(4,4)
or:
print(np.array(list(b)).reshape(4, -1))
print(np.array(list(b)).reshape(-1, 4))
So i want to take each value from a list in a 2d array into its own separate 2d array for use later.
I have this code:
for i in portalsAll:
for x in i:
tpinx.append(x.split(" ")[0])
tpiny.append(x.split(" ")[1])
tpoutx.append(x.split(" ")[2])
tpouty.append(x.split(" ")[3])
tpIn_x.append(tpinx)
tpIn_y.append(tpiny)
tpOut_x.append(tpoutx)
tpOut_y.append(tpouty)
and this is the 2d array i wish to take the values from:
[['0 0 1 2', '0 2 2 0', '2 2 1 0'], ['1 0 2 0', '8 0 3 0', '0 0 9 0']]
As you can see, there are spaces between the values, which i cannot delete as i took this data from a file, and is why i split it to remove the spaces.
However this code does not work and it replies for tpIn_x ,as an example,
[['0', '0', '2', '1', '8', '0'], ['0', '0', '2', '1', '8', '0']]
which is a 2d array consisting of 2 repeated lists.
My ideal output is
[['0', '0', '2'], ['1', '8', '0']]
where it would only put the data in each list from the corresponding list in the original 2d array, by the way the list sizes in the 2d array is not set to 3 so i cannot set a maximum list size.
How can i fix this? Any help is gratefully accepted.
for i in portalsAll:
tpIn_x.append([x.split()[0] for x in i])
tpIn_y.append([x.split()[1] for x in i])
tpOut_x.append([x.split()[2] for x in i])
tpOut_y.append([x.split()[3] for x in i])
This question already has answers here:
How to sort python list of strings of numbers
(4 answers)
Closed 6 years ago.
I have a file with 4 column data, and I want to prepare a final output file which is sorted by the first column. The data file (rough.dat) looks like:
1 2 4 9
11 2 3 5
6 5 7 4
100 6 1 2
The code I am using to sort by the first column is:
with open('rough.dat','r') as f:
lines=[line.split() for line in f]
a=sorted(lines, key=lambda x:x[0])
print a
The result I am getting is strange, and I think I'm doing something silly!
[['1', '2', '4', '9'], ['100', '6', '1', '2'], ['11', '2', '3', '5'], ['6', '5', '7', '4']]
You may see that the first column sorting is not done as per ascending order, instead, the numbers starting with 'one' takes the priority!! A zero after 'one' i.e 100 takes priority over 11!
Strings are compared lexicographically (dictionary order):
>>> '100' < '6'
True
>>> int('100') < int('6')
False
Converting the first item to int in key function will give you what you want.
a = sorted(lines, key=lambda x: int(x[0]))
You are sorting your numbers literally because they are strings not integers. As a more numpythonic way you can use np.loadtext in order to load your data then sort your rows based on second axis:
import numpy as np
array = np.loadtxt('rough.dat')
array.sort(axis=1)
print array
[[ 1. 2. 4. 9.]
[ 2. 3. 5. 11.]
[ 4. 5. 6. 7.]
[ 1. 2. 6. 100.]]
A B C D
2 4 5 6
4 5 3 7
3 6 7 8
I want to get A, B, C column values to array(3 x 3) and D column to another array(3 x 1).
simple brute-force method:
a33 = [[],[],[]]
a31 = []
with open('dat.txt') as f:
for ln in f:
a,b,c,d = ln.split()
a33[0] += a
a33[1] += b
a33[2] += c
a31 += d
print a33
print a31
[['2', '4', '3'], ['4', '5', '6'], ['5', '3', '7']]
['6', '7', '8']
import numpy as np
# Read the data from a file
with open('data.txt') as file:
lines = file.readlines()
# Chop of the columns
raw_data = lines[1:]
# Now fetch all the data
data_abc = []
data_d = []
for line in raw_data:
values = line.split()
data_abc.append(values[:3])
data_d.append(values[3])
# Convert to matrix
data_abc = np.asmatrix(data_abc)
data_d = np.asmatrix(data_d)
# Display the result
print('Data A B C:', data_abc)
print('Data D:', data_d)
I am a very beginner in Python and have the next 'problem'. I would be glad, if you could help me)
I have a *.dat file (let's name it file-1, first row is just a headline which I use only here to mark the columns) which looks like:
1 2 3 4 5 6
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
6 5 -1000 "" "" ""
I need it to be like (file-1 (converted)):
6 5 1 -1000
6 5 1 -1000
6 5 2 -1000
6 5 3 -1000
6 5 3 -1000
6 5 3 -1000
6 5 3 -1000
So, file-1 has 9 rows (7 with information and 2 empty) and 6 columns and I have to do the next:
Delete the last 3 columns in the file-1.
Add 1 new column that will take place between the columns 2 and 3.
The value of this new column should be increased by 1 unit (like '+= 1') after passing the empty line.
Delete all the empty lines. The result is represented as the 'file-1 (converted)'.
I've tried to do this but stucked. For now I am on the level of:
import sys
import csv
with open("file-1.dat", "r", newline="") as f:
sys.stdout = open('%s2 (converted).txt' % f.name, 'a')
incsv = csv.reader(f, delimiter="\t")
for row in incsv:
if len(row) == 6:
i = 0
row = row[0:3]
row.insert(2, i)
print(row)
and it looks like:
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
I don't know for now how to change 0 to 1 and 2 and so on, so it could be like:
['6', '5', 0, '-1000']
['6', '5', 0, '-1000']
['6', '5', 1, '-1000']
['6', '5', 2, '-1000']
['6', '5', 2, '-1000']
['6', '5', 2, '-1000']
['6', '5', 2, '-1000']
And the result should be like the 'file-1 (converted)' file.
P.S. All the examples are simplified, real file has a lot of rows and I don't know where the empty lines appear.
P.P.S. Sorry for such a long post, hope, it makes sense. Ask, suggest - I would be really glad to see other opinions) Thank you.
seems like you're almost there, you're just inserting i=0 all the time instead of the count of empty rows, try something like:
with open("file-1.dat", "r", newline="") as f:
sys.stdout = open('%s2 (converted).txt' % f.name, 'a')
incsv = csv.reader(f, delimiter="\t")
empties = 0 # init empty row counter
for row in incsv:
if len(row) == 6:
row = row[0:3]
row.insert(2, empties) # insert number of empty rows
print(row)
else:
empties += 1 # if row is empty, increase counter
This is bit different without using csv module. Hope this helps. :)
import sys
count = 0
with open("file-1.dat", "r") as f:
sys.stdout = open('%s2 (converted).txt' % f.name, 'a')
for line in f:
converted_line = line.split()[:-3] #split each line and remove last 3 column
if not converted_line: # if list/line is empty
count += 1 #increase count but DO NOT PRINT/ WRITE TO FILE
else:
converted_line.insert(2,str(count)) # insert between 2nd and 3rd column
print ('\t'.join(converted_line)) # join them and print them with tab delimiter
You need to increment i on every empty line
import sys
import csv
with open("file-1.dat", "r") as f:
sys.stdout = open('%s2 (converted).txt' % f.name, 'a')
incsv = csv.reader(f, delimiter="\t")
incsv.next() # ignore first line
i = 0
for row in incsv:
if len(row) == 6:
row = row[0:3]
row.insert(2, i)
print(row)
elif len(row) == 0:
i += 1
Also, I couldn't execute your code on my machine (with Python 2.7.6). I changed the code according to run with Python 2.x.
Edit: I see it runs with Python 3.x