Python3 read file and place 2D array with int value one line - python

I'm interested that this 2 lines can be solved in 1 line:
data = [ line.strip().split() for line in f ] # f = file
data = [ [ int(num) for num in nums ] for nums in data ]
Example lines of file:
9 3 14 3 10 17
9 8 19 12 5 9
Example result:
[[9, 3, 14, 3, 10, 17], [9, 8, 19, 12, 5, 9]]

Try:
f = open("file.txt", "r")
data = [[int(num) for num in line.split()] for line in f.readlines()]
print(data)
[[9, 3, 14, 3, 10, 17], [9, 8, 19, 12, 5, 9]]
or using numpy can be slightly neater:
import numpy as np
data = np.loadtxt("file.txt", dtype=int).tolist()

Related

Numpy python R eqivalent indexing

import numpy as np
o = np.array([
[
[1,2,3,4],
[5,6,7,8]
],
[
[9,10,11,12],
[13,14,15,16]
]
])
print(o.flatten())
# array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
It first flattens the row of each matrix
But I want that it flattens the coluumn of each matrix first so that it prints
[1,5,2,6,3,7,4,8,9,13,10,14,11,15,12,16]
I tried searching and what I found was passing "F" as an argument but that gives [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
that is it switches to another matrix without completing first.
In short, I would like to find python equivalent of R's indexing with double brackets
someData <- rep(0, 2*3*4);
ar <- array(someData, c(2, 3, 4));
ar[1,1,1] = 1
ar[1,2,1] = 2
ar[1,3,1] = 3
ar[2,1,1] = 4
ar[2,2,1] = 5
ar[2,3,1] = 6
ar[1,1,2] = 7
ar[1,2,2] = 8
ar[1,3,2] = 9
print(ar[[1]]) # 1
print(ar[[2]]) # 4
print(ar[[3]]) # 2
print(ar[[4]]) # 5
print(ar[[5]]) # 3
print(ar[[6]]) # 6
You can start by doing a np.concatenate on the second dimension, and then flatten in column-major order as you also mentioned:
np.concatenate(o, axis=1).flatten(order='f')
Output
array([ 1, 5, 2, 6, 3, 7, 4, 8, 9, 13, 10, 14, 11, 15, 12, 16])

Can my code be more simple?

An n-by-n square matrix (table of numbers) is a magic matrix if the sum of its row and the sum of each column are identical. For example, the 4-by-4 matrix below is a magic matrix. The sum of every row and the sum of every column are exactly the same value 34.
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Write a function that takes a 4-by-4 matrix as an argument and then determine if the matrix is magic or not. The
#matrix should be stored as a two-dimensional list. Test your function with a magic matrix and a none magic matrix.
def magic(matrix = []):
magic_matrix = False
if len(matrix) != 4:
print('Enter a 4 * 4 matrix')
return magic_matrix
row1Sum = sum(matrix[0])
rowSum_ok = True
for row in range(1, 4):
if sum(matrix[row]) != row1Sum:
rowSum_ok = False
break
colSum_ok = True
for col in range(4):
s_col = 0
for row in range(4):
s_col += matrix[row][col]
if s_col != row1Sum:
colSum_ok = False
break
if rowSum_ok and colSum_ok:
magic_matrix = True
return magic_matrix
def mainMagic():
m1 = [[9, 6, 3, 16],
[4, 15, 10, 5],
[14, 1, 8, 11],
[7, 12, 13, 2]]
print('\nThe matrix:')
for i in range(4):
for j in m1[i]:
print(str(j).rjust(3), end =' ')
print()
if magic(m1):
print('is a magic matrix.')
else:
print('is not a magic matrix.')
m2 = [[6, 22, 44, 18],
[1, 11, 10, 13],
[3, 17, 6, 12],
[9, 14, 2, 1]]
print('\nThe matrix:')
for i in range(4):
for j in m2[i]:
print(repr(j).rjust(3), end = ' ')
print()
if magic(m2):
print('is a magic matrix.')
else:
print('is not a magic matrix.')
mainMagic()
With a couple of set comprehensions and a zip() that is fairly straight forward to cleanup like:
Code:
def is_magic(matrix):
sum_rows = {sum(row) for row in matrix}
sum_cols = {sum(col) for col in zip(*matrix)}
return len(sum_cols) == 1 and sum_cols == sum_rows
Test Code:
m1 = [[9, 6, 3, 16],
[4, 15, 10, 5],
[14, 1, 8, 11],
[7, 12, 13, 2]]
m2 = [[6, 22, 44, 18],
[1, 11, 10, 13],
[3, 17, 6, 12],
[9, 14, 2, 1]]
print(is_magic(m1))
print(is_magic(m2))
Results:
True
False

Pythonic way to get both diagonals passing through a matrix entry (i,j)

What is the Pythonic way to get a list of diagonal elements in a matrix passing through entry (i,j)?
For e.g., given a matrix like:
[1 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
and an entry, say, (1,3) (representing element 9) how can I get the elements in the diagonals passing through 9 in a Pythonic way? Basically, [3,9,15] and [5,9,13,17,21] both.
Using np.diagonal with a little offset logic.
import numpy as np
lst = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
i, j = 1, 3
major = np.diagonal(lst, offset=(j - i))
print(major)
array([ 3, 9, 15])
minor = np.diagonal(np.rot90(lst), offset=-lst.shape[1] + (j + i) + 1)
print(minor)
array([ 5, 9, 13, 17, 21])
The indices i and j are the row and column. By specifying the offset, numpy knows from where to begin selecting elements for the diagonal.
For the major diagonal, You want to start collecting from 3 in the first row. So you need to take the current column index and subtract it by the current row index, to figure out the correct column index at the 0th row. Similarly for the minor diagonal, where the array is flipped (rotated by 90˚) and the process repeats.
As another alternative method, with raveling the array and for matrix with shape (n*n):
array = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
x, y = 1, 3
a_mod = array.ravel()
size = array.shape[0]
if y >= x:
diag = a_mod[y-x:(x+size-y)*size:size+1]
else:
diag = a_mod[(x-y)*size::size+1]
if x-(size-1-y) >= 0:
reverse_diag = array[:, ::-1].ravel()[(x-(size-1-y))*size::size+1]
else:
reverse_diag = a_mod[x:x*size+1:size-1]
# diag --> [ 3 9 15]
# reverse_diag --> [ 5 9 13 17 21]
The correctness of the resulted arrays must be checked further. This can be developed to handle matrices with other shapes e.g. (n*m).

Python CSV transpose data in one column to rows

I have a CSV file containing data only in the first column,
I want to use python to transpose every 4 rows to another empty CSV file, for example, row 1 to row 4 transposed to the first row; then row 5 to row 8 transposed to the second row,...etc, and finally we can get a 5 * 4 matrix in the CSV file.
How to write a script to do this? Please give me any hint and suggestion, thank you.
I am using python 2.7.4 under Windows 8.1 x64.
update#1
I use the following code provided by thefortheye,
import sys, os
os.chdir('C:\Users\Heinz\Desktop')
print os.getcwd()
from itertools import islice
with open("test_csv.csv") as in_f, open("Output.csv", "w") as out_file:
for line in ([i.rstrip()] + map(str.rstrip, islice(in_f, 3)) for i in in_f):
out_file.write("\t".join(line) + "\n")
the input CSV file is,
and the result is,
This is not what I want.
You can use List comprehension like this
data = range(20)
print data
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
print[data[i:i + 4] for i in xrange(0, len(data), 4)]
# [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18,19]]
Instead of 4, you might want to use 56.
Since you are planing to read from the file, you might want to do something like this
from itertools import islice
with open("Input.txt") as in_file:
print [[int(line)] + map(int, islice(in_file, 3)) for line in in_file]
Edit As per the updated question,
from itertools import islice
with open("Input.txt") as in_f, open("Output.txt", "w") as out_file:
for line in ([i.rstrip()] + map(str.rstrip, islice(in_f, 3)) for i in in_f):
out_file.write("\t".join(line) + "\n")
Edit: Since you are looking for comma separated values, you can join the lines with ,, like this
out_file.write(",".join(line) + "\n")
You can use List comprehension and double-loop like this.
>>> M = 3
>>> N = 5
>>> a = range(M * N)
>>> o = [[a[i * N + j] for j in xrange(N)] for i in xrange(M)]
>>> print o
[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]

text file format from array

I have no: of arrays, and i like to take it to text file in specific format, for eg.,
'present form'
a= [1 2 3 4 5 ]
b= [ 1 2 3 4 5 6 7 8 ]
c= [ 8 9 10 12 23 43 45 56 76 78]
d= [ 1 2 3 4 5 6 7 8 45 56 76 78 12 23 43 ]
The 'required format' in a txt file,
a '\t' b '\t' d '\t' c
1 '\t' 1
2 '\t' 2
3 '\t' 3
4 '\t' 4
5 '\t' 5
6
7
8
'\t'- 1 tab space
problem is,
I have the array in linear form[a],[b],[c],and d, i have to transpose('required format') and sort [a],[b],[d],and [c] and write it as a txt file
from __future__ import with_statement
import csv
import itertools
a= [1, 2, 3, 4, 5]
b= [1, 2, 3, 4, 5, 6, 7, 8]
c= [8, 9, 10, 12, 23, 43, 45, 56, 76, 78]
d= [1, 2, 3, 4, 5, 6, 7, 8, 45, 56, 76, 78, 12, 23, 43]
with open('destination.txt', 'w') as f:
cf = csv.writer(f, delimiter='\t')
cf.writerow(['a', 'b', 'd', 'c']) # header
cf.writerows(itertools.izip_longest(a, b, d, c))
Results on destination.txt (<tab>s are in fact real tabs on the file):
a<tab>b<tab>d<tab>c
1<tab>1<tab>1<tab>8
2<tab>2<tab>2<tab>9
3<tab>3<tab>3<tab>10
4<tab>4<tab>4<tab>12
5<tab>5<tab>5<tab>23
<tab>6<tab>6<tab>43
<tab>7<tab>7<tab>45
<tab>8<tab>8<tab>56
<tab><tab>45<tab>76
<tab><tab>56<tab>78
<tab><tab>76<tab>
<tab><tab>78<tab>
<tab><tab>12<tab>
<tab><tab>23<tab>
<tab><tab>43<tab>
Here's the izip_longest function, if you have python < 2.6:
def izip_longest(*iterables, fillvalue=None):
def sentinel(counter=([fillvalue]*(len(iterables)-1)).pop):
yield counter()
fillers = itertools.repeat(fillvalue)
iters = [itertools.chain(it, sentinel(), fillers)
for it in iterables]
try:
for tup in itertools.izip(*iters):
yield tup
except IndexError:
pass
Have a look at matplotlib.mlab.rec2csv and csv2rec:
>>> from matplotlib.mlab import rec2csv,csv2rec
# note: these are also imported automatically when you do ipython -pylab
>>> rec = csv2rec('csv file.csv')
>>> rec2csv(rec, 'copy csv file', delimiter='\t')
Just for fun with no imports:
a= [1, 2, 3, 4, 5]
b= [1, 2, 3, 4, 5, 6, 7, 8]
c= [8, 9, 10, 12, 23, 43, 45, 56, 76, 78]
d= [1, 2, 3, 4, 5, 6, 7, 8, 45, 56, 76, 78, 12, 23, 43]
fh = open("out.txt","w")
# header line
fh.write("a\tb\td\tc\n")
# rest of file
for i in map(lambda *row: [elem or "" for elem in row], *[a,b,d,c]):
fh.write("\t".join(map(str,i))+"\n")
fh.close()

Categories