Adding None Value Always gives 0 - python

I want to create a function that adds the numbers in the columns in a matrix and output a vector made of the sum. However if there is a "None" value in the matrix, the output vector gets a "None" value for that column automatically. I cannot figure out how to do the part for the "None" value.
I tried the following code.
def sum_matrix (matrix):
#
# | 1 2 3 |
# | 1 2 3 |
# | 1 2 3 | -> |4 8 12|
# | 1 2 3 |
# _________
# 4 8 12
vektor = [[0] for i in range(0,len(matrix[0]))]
for j in range(0, len(matrix[0])): #rows 0-3 4
buffer = 0
for i in range(0, len(matrix)): #columns 3
if matrix[i][j] !=None:
buffer = buffer + matrix[i][j]
#vektor[j][0] = buffer
elif matrix[i][j] ==None:
vektor[j][0] = None
vektor[j][0] = buffer
return vektor
print (sum_matrix ([[0,0,0],[0,0,1],[0,1,0],[0,0,0]]))
print (sum_matrix ([[0,0,0],[0,None,1],[0,1,None],[0,0,0]]))
For sum_matrix ([[0,0,0],[0,0,1],[0,1,0],[0,0,0]]), I get [[0],[1],[1]] which is good.
For sum_matrix ([[0,0,0],[0,None,1],[0,1,None],[0,0,0]]), I still get [[0],[1],[1]] even though I am supposed to get [[0],[None],[None]]

As I always say, you should differentiate a matrix (a mathematical abstraction) from its implementation (a list of lists).
Now, what we have here is basically a list of lists where each inner list represents a row, but we want to take the sum of each column, with the additional constraint that it should be None whenever it contains at least one None value.
The simplest way to do this, I would say, is using a list comprehension in conjunction with zip, which effectively transposes your matrix:
def sum_matrix(m):
transposed = zip(*m)
summed = [[sum(col) if None not in col else None]
for col in transposed]
return summed
print(sum_matrix([[0,0,0],[0,0,1],[0,1,0],[0,0,0]]))
print(sum_matrix([[0,0,0],[0,None,1],[0,1,None],[0,0,0]]))
Output:
[[0], [1], [1]]
[[0], [None], [None]]
Note: you can also couch the inner list comprehension as [None if None in col else sum(col)], but I prefer to put the "normal" case first.
You could also convert col to a set, which allows constant time lookups, but actual conversion to a set is linear time, and since we're only iterating over each column once, I don't think it'll be faster.

when matrix[i][j]==None you need to store in the buffer None, since you're changing the value of vektor when exiting the inner loop, so the vektor will always take the value of the buffer
def sum_matrix (matrix):
#
# | 1 2 3 |
# | 1 2 3 |
# | 1 2 3 | -> |4 8 12|
# | 1 2 3 |
# _________
# 4 8 12
vektor = [[0] for i in range(0,len(matrix[0]))]
for j in range(0, len(matrix[0])): #rows 0-3 4
buffer = 0
for i in range(0, len(matrix)): #columns 3
if matrix[i][j] !=None:
buffer = buffer + matrix[i][j]
#vektor[j][0] = buffer
elif matrix[i][j] ==None:
buffer = None
break
vektor[j][0] = buffer
return vektor

Related

Running perfectly on IDE but line (if mat[j] == mat[colindex]:) is giving index out of range error when submitting on geeks for geeks

t = int(input())
lis =[]
for i in range(t):
col = list(map(int,input()))
colindex = col[0] - 1
count = 0
matsize = col[0] * col[0]
mat = list(map(int,input().split()))
while len(lis) != matsize:
for j in range(len(mat)):
if colindex < len(mat):
if mat[j] == mat[colindex]:
lis.append(mat[j])
colindex += col[0]
count += 1
colindex = col[0] - 1
colindex -= count
for i in lis:
print(i,end= ' ')
Given a square matrix mat[][] of size N x N. The task is to rotate it by 90 degrees in anti-clockwise direction without using any extra space.
Input:
The first line of input contains a single integer T denoting the number of test cases. Then T test cases follow. Each test case consist of two lines. The first line of each test case consists of an integer N, where N is the size of the square matrix.The second line of each test case contains N x N space separated values of the matrix mat.
Output:
Corresponding to each test case, in a new line, print the rotated array.
Constraints:
1 ≤ T ≤ 50
1 ≤ N ≤ 50
1 <= mat[][] <= 100
Example:
Input:
2
3
1 2 3 4 5 6 7 8 9
2
5 7 10 9
Output:
3 6 9 2 5 8 1 4 7
7 9 5 10
Explanation:
Testcase 1: Matrix is as below:
1 2 3
4 5 6
7 8 9
Rotating it by 90 degrees in anticlockwise directions will result as below matrix:
3 6 9
2 5 8
1 4 7
https://practice.geeksforgeeks.org/problems/rotate-by-90-degree/0
It doesn't look like there is a problem with j. Can colindex ever be below 0? One way to identify this would be to simply keep track of the counters. For example, you can add an extra if condition if colindex >= 0: before if mat[j] == mat[colindex].
Rather than using one dimensional list, we can use two dimensional list to solve this challenge. From the given statement and sample test case, we get the following information:
Print the rotated matrix in a single line.
If the given matrix has n columns, the rotated matrix will have the sequential elements of n-1th column, n-2th column, .. 0th column.
Here is my accepted solution of this challenge:
def get_rotated_matrix(ar, n):
ar_2d = []
for i in range(0, len(ar)-n+1, n):
ar_2d.append(ar[i:i+n])
result = []
for i in range(n-1, -1, -1):
for j in range(n):
result.append(str(ar_2d[j][i]))
return result
cas = int(input())
for t in range(cas):
n = int(input())
ar = list(map(int, input().split()))
result = get_rotated_matrix(ar, n)
print(" ".join(result))
Explanation:
To make the solution simple, I created a 2 dimensional list to store the input data as a 2D matrix called ar_2d.
Then I traverse the matrix column wise; from last column to first column and appended the values to our result list as string value.
Finally, I have printed the result with space between elements using join method.
Disclaimer:
My solution uses a 1D list to store the rotated matrix elements thus usages extra space.

Join elements by iterating through the data

I have some data in the form:
ID A B VALUE EXPECTED RESULT
1 1 2 5 GROUP1
2 2 3 5 GROUP1
3 3 4 6 GROUP2
4 3 5 5 GROUP1
5 6 4 5 GROUP3
What i want to do is iterate through the data (thousand of rows) and create a common field so i will be able to join the data easily ( *A-> start Node, B->End Node Value-> Order...the data form something like a chain where only neighbors share a common A or B)
Rules for joining:
equal value for all elements of a group
A of element one equal to B of element two (or the oposite but NOT A=A' or B=B')
The most difficult one: assign to same group all sequential data that form a series of intersecting nodes.
That is the first element [1 1 2 5] has to be joined with [2 2 3 5] and then with [4 3 5 5]
Any idea how to accomplish this robustly when iterating through a large number of data? I have problem with rule number 3, the others are easily applied. For limited data i have some success, but this depends on the order i start examining the data. And this doesn't work for the large dataset.
I can use arcpy (preferably) or even Python or R or Matlab to solve this. Have tried arcpy with no success so i am checking on alternatives.
In ArcPy this code works ok but to limited extend (i.e. in large features with many segments i get 3-4 groups instead of 1):
TheShapefile="c:/Temp/temp.shp"
desc = arcpy.Describe(TheShapefile)
flds = desc.fields
fldin = 'no'
for fld in flds: #Check if new field exists
if fld.name == 'new':
fldin = 'yes'
if fldin!='yes': #If not create
arcpy.AddField_management(TheShapefile, "new", "SHORT")
arcpy.CalculateField_management(TheShapefile,"new",'!FID!', "PYTHON_9.3") # Copy FID to new
with arcpy.da.SearchCursor(TheShapefile, ["FID","NODE_A","NODE_B","ORDER_","new"]) as TheSearch:
for SearchRow in TheSearch:
if SearchRow[1]==SearchRow[4]:
Outer_FID=SearchRow[0]
else:
Outer_FID=SearchRow[4]
Outer_NODEA=SearchRow[1]
Outer_NODEB=SearchRow[2]
Outer_ORDER=SearchRow[3]
Outer_NEW=SearchRow[4]
with arcpy.da.UpdateCursor(TheShapefile, ["FID","NODE_A","NODE_B","ORDER_","new"]) as TheUpdate:
for UpdateRow in TheUpdate:
Inner_FID=UpdateRow[0]
Inner_NODEA=UpdateRow[1]
Inner_NODEB=UpdateRow[2]
Inner_ORDER=UpdateRow[3]
if Inner_ORDER==Outer_ORDER and (Inner_NODEA==Outer_NODEB or Inner_NODEB==Outer_NODEA):
UpdateRow[4]=Outer_FID
TheUpdate.updateRow(UpdateRow)
And some data in shapefile form and dbf form
Using matlab:
A = [1 1 2 5
2 2 3 5
3 3 4 6
4 3 5 5
5 6 4 5]
%% Initialization
% index of matrix line sharing the same group
ind = 1
% length of the index
len = length(ind)
% the group array
g = []
% group counter
c = 1
% Start the small algorithm
while 1
% Check if another line with the same "Value" share some common node
ind = find(any(ismember(A(:,2:3),A(ind,2:3)) & A(:,4) == A(ind(end),4),2));
% If there is no new line, we create a group with the discovered line
if length(ind) == len
%group assignment
g(A(ind,1)) = c
c = c+1
% delete the already discovered line (or node...)
A(ind,:) = []
% break if no more node
if isempty(A)
break
end
% reset the index for the next group
ind = 1;
end
len = length(ind);
end
And here is the output:
g =
1 1 2 1 3
As expected

How to get average of increasing values using Pandas?

I'm trying to figure out the average of increasing values in my table per column.
my table
A | B | C
----------------
0 | 5 | 10
100 | 2 | 20
50 | 2 | 30
100 | 0 | 40
function I'm trying to write for my problem
def avergeIncreace(data,value): #not complete but what I have so far
x = data[value].pct_change().fillna(0).gt(0)
print( x )
pct_change() returns a table of the percentage of the number at that index compared to the number in row before it.fillna(0) replaces the NaN in position 0 of the chart that pct_change() creates with 0.gt(0) returns true or false table depending if the value at that index is greater than 0
current output of this function
In[1]:avergeIncreace(df,'A')
Out[1]: 0 False
1 True
2 False
3 True
Name: BAL, dtyle: bool
desired output
In[1]:avergeIncreace(df,'A')
Out[1]:75
In[2]:avergeIncreace(df,'B')
Out[2]:0
In[3]:avergeIncreace(df,'C')
Out[3]:10
From my limited understanding of pandas there should be a way to return an array of all the indexes that are true and then use a for loop and go through the original data table, but I believe pandas should have a way to do this without a for loop.
what I think the for loop way would look plus missing code so indexes returned are ones that are true instead of every index
avergeIncreace(df,'A')
indexes = data[value].pct_change().fillna(0).gt(0).index.values #this returns an array containing all of the index (true and false)
answer = 0
times = 0
for x in indexes:
answer += (data[value][x] - data[value][x-1])
times += 1
print( answer/times )
How to I achieve my desired output without using a for loop in the function?
You can use mask() and diff():
df.diff().mask(df.diff()<=0, np.nan).mean().fillna(0)
Yields:
A 75.0
B 0.0
C 10.0
dtype: float64
How about
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [0, 100, 50, 100],
'B': [5, 2, 2, 0],
'C': [10, 20, 30, 40]})
def averageIncrease(df, col_name):
# Create array of deltas. Replace nan and negative values with zero
a = np.maximum(df[col_name] - df[col_name].shift(), 0).replace(np.nan, 0)
# Count non-zero values
count = np.count_nonzero(a)
if count == 0:
# If only zero values… there is no increase
return 0
else:
return np.sum(a) / count
print(averageIncrease(df, 'A'))
print(averageIncrease(df, 'B'))
print(averageIncrease(df, 'C'))
75.0
0
10.0

Finding the max value in a python loop

I have a list of data that I'm trying to find the max value from with python. My current code will loop over the data and render all possible combinations of the data, however I can't figure out how to render the max from the results.
Below is my current setup:
street = %sql SELECT * FROM streets
for i in range(len(flight)):
for j in range(len(flight)):
for k in range(len(flight)):
A = flight[i][2]
B = flight[k][2]
num = flight[i][4] , flight[j][4] , flight[k][4]
numsum = sum(num)
print A, B, numsum
Printing flight will render the below
+----+-----------+----------------------+----------------------+---+
| id | flight | Start | End |dis|
+----+-----------+----------------------+----------------------+---+
| 0 | w | SFO | DEN | 4 |
| 1 | e | DEN | NYC | 7 |
| 1 | e | DEN | ORD | 7 |
However the max with throw the below error.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-283-770cd29ebd83> in <module>()
8 num = street[i][4] , street[j][4] , street[k][4]
9 numsum = sum(num)
---> 10 print A, B, max(numsum)
11
TypeError: 'int' object is not iterable
If I remove the max from the last line everything in the database will print. For example:
SFO ORD 35
DEN JFK 12
SFO JFK 94
LAX DEN 54
...
Can someone help me figure out how to get the max value in numsum so the result prints like this:
SFO JFK 94
Thanks in advance!
You're not doing what you're trying to do. Your algorithm isn't well thought-out. look at it this way:
for each_item in whatever_iterator:
a = each_item[some_element]
b = each_item[another_element]
num = some, other, numbers
sumnum = sum(num) # hey that was easy!
print a, b, sumnum # every time through, let's print it!
Nowhere does this find the LARGEST. In order to do that, you'd want to iterate through and save current_max = max(current_max, new_value)
Looks like what you're looking to do is:
max_sumnum = (0, 0, 0)
for i, j, k in itertools.product(len(x), repeat=3):
num = x[i][4], x[j][4], x[???][1][k][4]
cur_sumnum = x[i][2], x[k][2], sum(num)
max_sumnum = max(max_numsum, cur_sumnum, key=lambda tup: tup[2])
print max_sumnum
I use itertools.product here because it's a great shortcut for nested for loops.
for i in range(3):
for j in range(5):
for k in range(100):
for m in range(2):
foo(i, j, k, m)
# equivalent to....
for i, j, k, m in itertools.product(range(3), range(5),
range(100), range(2)):
And I use the repeat keyword since you're doing a bunch of the same loops.
for i in range(3):
for j in range(3):
for k in range(3):
# equivalent to....
for i, j, k in itertools.product(range(3), repeat=3):

How to create a table without using methods or for-loops?

I'm trying to create a 4x3 table without methods or for-loops.
I'd like to use what I learned in class, which is booleans, if-statements, and while-loops.
I want it so that if I input create_table('abcdefghijkl') it would start from the the left top most row and column and go down until the end of the column and then start again at the top of the next column and so on, like displayed below:
| a | e | i |
| b | f | j |
| c | g | k |
| d | h | l |
Below is what I have so far. It's not complete. How do I add to the function so that after 4 rows down, the string should continue to the next column starting from the top?
I'm wracking my brain over this.
All examples I can find online uses for loops and methods to create tables such as these, but I'd like to implement the while loop for this one.
Thanks in advance!
def create_table(table):
t = "" + "|" + ""
i = 0
while i < 12:
t = t + " " + "|" + table[i] + " "
i=i+1
print(t)
return table
Think about it in terms of rows instead of columns. You're writing out a row at a time, not a column at a time, so look at the indices of the individual cells in the original list:
| 0 | 4 | 8 |
| 1 | 5 | 9 |
| 2 | 6 | 10 |
| 3 | 7 | 11 |
Notice each row's cells' indices differ by 4. Find a simple expression for the nth row's cells and the task will become much easier, as you'll essentially be printing out a regular table.
You can translate most for loops to while loops with a simple recipe, so if you figure out how to do it with a for loop, then you are good to go. If you have
for x in s:
{statements}
Make it
i = 0
while i < len(s):
x = s[i]
{statements}
i += 1
It just won't work for some enumerable types that don't support length and indexing, such as generators.
Because you are printing to the terminal, you would want to think about printing each horizontal row, rather than each vertical column. Try something like:
table = 'abcdefghijkl'
i = 0
while i < 4:
print("| {} | {} | {} |".format(table[i], table[i+4], table[i+8]))
i += 1

Categories

Resources