matrix multiplying between files in python - python

import linecache
fileA = open('matrixA.txt', 'r' )
line2 = linecache.getline('matrixA.txt', 2)
line3 = linecache.getline('matrixA.txt', 3)
line4 = linecache.getline('matrixA.txt', 4)
two = line2.split()
list2 = list(map(int, two))
three = line3.split()
list3 = list(map(int,three))
four = line4.split()
list4 = list(map(int, four))
listA = [list2]+[list3]+[list4]
print (listA)
fileB = open('matrixB.txt', 'r')
Bline2 = linecache.getline('matrixB.txt', 2)
Bline3 = linecache.getline('matrixB.txt', 3)
Bline4 = linecache.getline('matrixB.txt', 4)
btwo = Bline2.split()
blist2 = list(map(int, btwo))
bthree = Bline3.split()
blist3 = list(map(int,bthree))
bfour = Bline4.split()
blist4 = list(map(int, bfour))
listB = [blist2] + [blist3] + [blist4]
print (listB)
q = listA[0] #
h = listB[0] #This part dosn't work
aq = q*h #
print(aq) #
//for i in range(listA):
So I have this code so far from my 2 files file A prints as:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
And file B prints as:
[[3, 3, 9], [7, 4, 8], [4, 20, 30]]
How would I get these two matrices to multiply, I know you would need positions but I don't know how to do the loop.

I assume you have loaded your *.txt data correctly (you start to read your data from the second line), then to multiply it the simple one is by converting it to numpy array and use np.dot.
import numpy as np
A = np.asarray(listA)
B = np.asarray(listB)
res = np.dot(B,A)
print(res)
or you can do that without numpy by indexing the list:
res = [[0] * len(listA[0]) for _ in range(len(listB))]
for i in range(len(listB)):
for j in range(len(listA[0])):
for k in range(len(listA)):
res[i][j] += listB[i][k]*listA[k][j]
print(res)
to make sure your matrix can be multiplied, check the dimension first:
if len(listA)==len(listB[0]):
res = [[0] * len(listA[0]) for _ in range(len(listB))]
for i in range(len(listB)):
for j in range(len(listA[0])):
for k in range(len(listA)):
res[i][j] += listB[i][k]*listA[k][j]
print(res)
else:
print("ERROR! Size Mismatch")

Related

Can anyone help me in handling ties in a python list while I try to replace it's elements with their ranks?

I have a list that looks something like this:
lst_A = [32,12,32,55,12,90,32,75]
I want to replace the numbers with their rank. I am using this function to do this:
def obtain_rank(lstC):
sort_data = [(x,i) for i,x in enumerate(lstC)]
sort_data = sorted(sort_data,reverse=True)
result = [0]*len(lstC)
for i,(_,idx) in enumerate(sort_data,1):
result[idx] = i
return result
I am getting the following output while I use this:
[6, 8, 5, 3, 7, 1, 4, 2]
But what I want from this is:
[4, 7, 5, 3, 8, 1, 6, 2]
How can I go about this?
Try this:
import pandas as pd
def obtain_rank(a):
s = pd.Series(a)
return [int(x) for x in s.rank(method='first', ascending=False)]
#[4, 7, 5, 3, 8, 1, 6, 2]
You could use 2 loops:
l = [32,12,32,55,12,90,32,75]
d = list(enumerate(sorted(l, reverse = True), start = 1))
res = []
for i in range(len(l)):
for j in range(len(d)):
if d[j][1] == l[i]:
res.append(d[j][0])
del d[j]
break
print(res)
#[4, 7, 5, 3, 8, 1, 6, 2]
Here you go. In case, you are not already aware, please read https://docs.python.org/3.7/library/collections.html to understand defaultdict and deque
from collections import defaultdict, deque
def obtain_rank(listC):
sorted_list = sorted(listC, reverse=True)
d = defaultdict(deque) # deque are efficient at appending/popping elements at both sides of the sequence.
for i, ele in enumerate(sorted_list):
d[ele].append(i+1)
result = []
for ele in listC:
result.append(d[ele].popleft()) # repeating numbers with lower rank will be the start of the list, therefore popleft
return result
Update: Without using defaultdict and deque
def obtain_rank(listC):
sorted_list = sorted(listC, reverse=True)
d = {}
for i, ele in enumerate(sorted_list):
d[ele] = d.get(ele, []) + [i + 1] # As suggested by Joshua Nixon
result = []
for ele in listC:
result.append(d[ele][0])
del d[ele][0]
return result

Python String to Array conversion

My requirement is to take 'arrList' string as an argument from main and split it using comma (,) and each name is an Array (arr1, arr2, arr3). Now all 3 arrays should be appended to a list. The output should be : list: 1,2,3,7,8,9,11,22,33. But should follow below steps only while implementing.
Tried below code, but not able to convert. Any help is appreciated.
arr1 = [1,2,3]
arr2 = [7,8,9]
arr3 = [11,22,33]
list = []
def arrTest(arrList):
var = arrList.split(',')
for x in var:
#f = open(, "r")
#for x in f:
# list.append(x.rstrip('\n'))
if __name__ == '__main__':
arrList = "arr1,arr2,arr3"
arrTest(arrList)
arr1 = [1,2,3]
arr2 = [7,8,9]
arr3 = [11,22,33]
the_list = []
arrList = "arr1,arr2,arr3"
for array in arrList.split(','):
if array in locals():
the_list.extend(locals()[array])
print (the_list)
Output
[1, 2, 3, 7, 8, 9, 11, 22, 33]
locals() function returns a dictionary containing the variables defined in the local namespace.
You can use python dict data structure.
arr1 = [1,2,3]
arr2 = [7,8,9]
arr3 = [11,22,33]
d = {"arr1": arr1, "arr2": arr2, "arr3": arr3}
def arrTest(arrList):
l = []
var = arrList.split(',')
for x in var:
for e in d[x]:
l.append(e)
return l
if __name__ == '__main__':
arrList = "arr1,arr2,arr3"
l = arrTest(arrList)
print(l)
Output
[1, 2, 3, 7, 8, 9, 11, 22, 33]
Use eval function
arr1 = [1,2,3]
arr2 = [7,8,9]
arr3 = [11,22,33]
out = []
def arrTest(arrList):
list_strs = arrList.split(',')
for list_str in list_strs:
l = eval(list_str)
out.extend(l)
arrList = "arr1,arr2,arr3"
arrTest(arrList)
print(out)
[1, 2, 3, 7, 8, 9, 11, 22, 33]

dropping the lowest values from a list

I'm trying to write a python program that drops 25% of the lowest values from a list and (return the original unsorted list). For example;
Input : [1,5,6,72,3,4,9,11,3,8]
Output : [5,6,72,4,9,11,8]
I tried to do:
l = [1,5,6,72,3,4,9,11,3,8]
def drop(k):
while len(l)!=0 and k > 0:
k = k - 1
l.sort(reverse = True)
l.pop()
return l
k = math.ceil(len(l) * 0.25)
drop (k)
it returns [72, 11, 9, 8, 6, 5, 4] but is there a way to do it without sorting?.
You don't require to reverse sort and find the smallest element. Use min on list l which returns the smallest value from l and remove using l.remove conveniently.
import math
l = [1,5,6,72,3,4,9,11,3,8]
def drop(k):
while len(l)!=0 and k > 0:
k = k - 1
l.remove(min(l))
return l
k = math.ceil(len(l) * 0.25)
print(drop (k))
# [5, 6, 72, 4, 9, 11, 8]
You could use a heapq and keep popping elements until 25% of the container has been removed. Then, filter the contents of the original list
import heapq, copy
s = [1,5,6,72,3,4,9,11,3,8]
new_s = copy.deepcopy(s)
heapq.heapify(s)
count = 0
last_items = set()
while count/float(len(new_s)) <= 0.25:
last_items.add(heapq.heappop(s))
count += 1
final_s = [i for i in new_s if i not in last_items]
Output:
[5, 6, 72, 4, 9, 11, 8]
There are O(n) solutions to this problem. One of those, introselect, is implemented in numpy in the partition and argpartition functions:
>>> data = [1,5,6,72,3,4,9,11,3,8]
>>>
>>> k = int(round(len(data) / 4))
>>>
>>> import numpy as np
>>> dnp = np.array(data)
>>> drop_them = np.argpartition(dnp, k)[:k]
>>> keep_them = np.ones(dnp.shape, dtype=bool)
>>> keep_them[drop_them] = False
>>> result = dnp[keep_them].tolist()
>>>
>>> result
[5, 6, 72, 4, 9, 11, 3, 8]
Note that this method keeps one of the 3s and drops the other one in order to get the split at exactly k elements.
If instead you want to treat all 3s the same, you could do
>>> boundary = np.argpartition(dnp, k)[k]
>>> result = dnp[dnp > dnp[boundary]]
>>>
>>> result
array([ 5, 6, 72, 4, 9, 11, 8])
One way of doing this is this is very slow especially for longer lists!:
quart_len = int(0.25*len(l))
for i in range(quart_len):
l.remove(min(l))
A much faster way of doing this:
import numpy as np
from math import ceil
l = [1,5,6,72,3,4,9,11,3,8]
sorted_values = np.array(l).argsort()
l_new = [l[i] for i in range(len(l)) if i in sorted_values[int(ceil(len(l)/4.)):]]
Another approach:
l = np.array(l)
l = list(l[l > sorted(l)[len(l)/4]])
l1=[1,5,6,72,3,4,9,11,3,8]
l2=sorted(l1)
ln=round(len(l1)*0.25)
[i for i in l1 if i not in l2[ln+1:]]
Output:
[5, 6, 72, 4, 9, 11, 8]

Adding specific items in list [x] for separate lists after importing .txt file in Python

I am importing labdata.txt in the code that follows. For statements, such as for i in values: will add each variable in a given parameter. For each set of parameters, e.g., [1, 3, 4,] [3, 5, 7], [67, 56, 56], my goal is to add [1] + [3] + [67] for example. Then to obtain the average of these three items.
The part that is unclear is how to take x = values[:1] and then somehow have it add that variable for x in the different parameters like explained above.
Here is the code so far:
lab_data = open("labdata.txt", "r") #import text
x = 0 # initialize variable
y = 0 # initialize variable
for aline in lab_data:
values = aline.split()
values = [int (u) for u in values]
print (values)
x = values[:1]
y = values[1:2]
print (x)
#print (y)
average = 0
ui = 0
other = 0
bs = 0
# print (sum(values[:1]))
for z in values[:1]:
other = (sum(values[:1]))
bs = bs + other
print (bs)
#print (sum(values[:1]))
ui = ui + z
average = ui / len(values)#this just gives the avg of x
print (average)
</pre>
Let me answer this very unclear question
I assume your question is: how to get an average from three different lists
lst1 = [1, 3, 4]
lst2 = [3, 5, 7]
lst3 = [67, 56, 56]
avg1 = sum([lst1[0],lst2[0],lst3[0]]) / 3
avg2 = sum([lst1[1],lst2[1],lst3[1]]) / 3
avg3 = sum([lst1[2],lst2[2],lst3[2]]) / 3
print avg1,avg2,avg3
If you are using python3, you can use statistics.mean with zip:
lst1 = [1, 3, 4]
lst2 = [3, 5, 7]
lst3 = [67, 56, 56]
from statistics import mean
a, b, c = map(mean, zip(lst1, lst2, lst3))
print(a, b, c)
For python2 create your own mean function:
from itertools import imap, izip
def mean(x):
return sum(x) / float(len(x))
a, b, c = imap(mean, izip(lst1, lst2, lst3))
print(a, b, c)
Letting each list have the same length, this is my solution:
lst1 = [1, 2, 3]
lst2 = [3, 4, 5]
lst3 = [3, 2, 1]
# list "lst" will contain the results for every index
lst =[]
for i in range(len(lst1)):
lst.append(lst1[i]/3 + lst2[i]/3 + lst3[i]/3)
print lst
I guess what you want is something like:
lab_data = open("labdata.txt", "r") #import text
int_data = [[int(val) for val in line.split()] for line in lines]
def mean(args): return float(sum(args))/len(args)
means = []
for i in range(0, len(int_data[0])):
means.append(mean([row[i] for row in int_data]))

Expand a range which looks like: "1-3,6,8-10" to [1,2,3, 6, 8,9,10]

I am trying to add an option to my program which allow the user to choose which steps of the program he wants to do.
I would like to be able to parse a string like "1-3,6,8-10" and get [1, 2, 3, 6, 8, 9, 10].
Do you know if something in Python which is doing that already exists ?
This function does what you asked. It assumes no negative numbers are used, otherwise it needs some changes to support that case.
def mixrange(s):
r = []
for i in s.split(','):
if '-' not in i:
r.append(int(i))
else:
l,h = map(int, i.split('-'))
r+= range(l,h+1)
return r
print mixrange('1-3,6,8-10')
One way using list comprehensions:
s = "1-3,6,8-10"
x = [ss.split('-') for ss in s.split(',')]
x = [range(int(i[0]),int(i[1])+1) if len(i) == 2 else i for i in x]
print([int(item) for sublist in x for item in sublist])
Outputs:
[1, 2, 3, 6, 8, 9, 10]
No builtin function as such, but can be done using xrange and generators:
from itertools import chain
s = "1-3,6,8-10"
spans = (el.partition('-')[::2] for el in s.split(','))
ranges = (xrange(int(s), int(e) + 1 if e else int(s) + 1) for s, e in spans)
all_nums = chain.from_iterable(ranges) # loop over, or materialse using `list`
# [1, 2, 3, 6, 8, 9, 10]
s = '1-3,6,8-10,13-16'
temp = [x.split('-') if '-' in x else x for x in s.split(',')]
# temp = [['1', '3'], '6', ['8', '10'], ['13', '16']]
res = []
for l in temp:
if isinstance(l, list):
a, b = map(int, l)
res += list(range(a, b + 1))
else:
res.append(int(l))
# res = [1, 2, 3, 6, 8, 9, 10, 13, 14, 15, 16]
A little function I just created:
def expand(st):
res = []
for item in st.split(','):
if '-' in item:
temp = map(int, item.split('-'))
res.extend(range(temp[0], temp[1]+1))
else:
res.append(int(item))
return res
s = '1-3,6,8-10'
print expand(s)
Returns:
[1, 2, 3, 6, 8, 9, 10]
def parseIntSet(nputstr=""):
selection = set()
invalid = set()
# tokens are comma seperated values
tokens = [x.strip() for x in nputstr.split(',')]
for i in tokens:
try:
# typically tokens are plain old integers
selection.add(int(i))
except:
# if not, then it might be a range
try:
token = [int(k.strip()) for k in i.split('-')]
if len(token) > 1:
token.sort()
# we have items seperated by a dash
# try to build a valid range
first = token[0]
last = token[len(token)-1]
for x in range(first, last+1):
selection.add(x)
except:
# not an int and not a range...
invalid.add(i)
# Report invalid tokens before returning valid selection
print "Invalid set: " + str(invalid)
return selection
Via: Parsing a list of numbers in Python
Aha, one line proof of concept anyone?
EDIT: Improved version
import itertools
s = "1-3,6,8-10"
print(list(itertools.chain.from_iterable(range(int(ranges[0]), int(ranges[1])+1) for ranges in ((el+[el[0]])[:2] for el in (miniRange.split('-') for miniRange in s.split(','))))))
Now split on several lines for readability:
print(list(itertools.chain.from_iterable(
range(
int(ranges[0]),
int(ranges[1])+1
)
for ranges in
(
(el+[el[0]])[:2] # Allows to get rid of the ternary condition by always adding a duplicate of the first element if it is alone
for el in
(miniRange.split('-') for miniRange in s.split(','))
)
)))

Categories