How create two points for y with the same x? - python

I'm trying to make a python code to create "double points", where one single value for x would assume two values for y for any situation. Here is a example of data:
1;5
2;-2
3;4
4;10.4
5;6
where first column(x), is just an index for position of the data (y).
Plotting this data into x and y, would form a straight line.
The result I would like to have is:
1;5
1;-2
2;-2
2;4
3;4
3;10.4
4;10.4
4;6
5;6
This would generate a rectangular chart. The value of x has its respective value of y, but that same value of x also has the value of y for its "x + 1", and so for the rest of the data.
I'm trying to do something like this, however unsuccessful:
l = [5, -2, 4, 10.4, 6]
m = []
i = 0
i = i+1
for i in range(len(l)):
m.append(l[i])
if i < len(l)-1:
m.append([l[i][0], l[i+1][1]])
print('{}, {}\n' .format(i, m[i]))
The error that appears is 'int' object has no attribute '__getitem__'
I am new to python and this is part of my studies, so if anyone can help me and can explain where I am going wrong, I would be grateful.
P.s the x column is not part of the data, is just an index (like time for example). And the data (y column) can be negative, floats... all of types of numbers

can be done using list comprehension like below
from itertools import chain
ls = [5, -2, 4, 10.4, 6]
list(chain(*([(i,v)]*2 for i, v in enumerate(ls))))[1:]

Try matching the items on each list depending on their index. E.g. with list.index(item):
y=[5, -2, 4, 10.4, 6]
x=[i for i in range(len(y)+1) if i!=0]
for item in x:
for i in y:
if x.index(item) == y.index(i):
print('%s;%s' %(item, i))
if x.index(item)==y.index(i) -1:
print('%s;%s' %(item, i))

Related

Is there an efficient way to find the shared value of two list elements, provided each has to contain another specified value?

This problem is a bit difficult to concisely explain in a single question line, so I'll start off by giving my code and saying that the printed value is the correct result:
valin = 4
valout = 3
gdict = {
(0,3): 0,
(1,3): 1,
(2,3): 2,
(0,4): 3,
(4,3): 4,
(0,5): 5,
(5,4): 6,
(4,6): 7,
(6,3): 8,
}
keys = list(gdict)
nin = [x for x in keys if x[0]==valin]
nout = [x for x in keys if x[1]==valout]
shared_val_from_vals = [x[1] for x in nin for y in nout if x[1]==y[0]][0]
print(shared_val_from_vals)
___________________________
6
I have two values: valin and valout. I'm looking for
one key where the 0th element equals valin and
another key where the 1st element equals valout and
the 1st element of the first key equals the 0th element of the second key
Then I will be using this shared value for another part of my code.
Although my code gets the job done, this code will be used with large dictionaries, so I would like to optimize these operations if I can. Is there a more pythonic or generally more concise way to accomplish this result?
Loop over the dictionary keys, creating sets of the tuple elements that match each criteria. Then intersect the two sets.
set_in = {}
set_out = {}
for in_var, out_var in gdict:
if in_var == valin:
set_out.append(out_var)
if out_var == valout:
set_in.append(in_var)
shared_val = set_in.intersect(set_out).pop()
You can only compact it by using a single for loop:
nin_out = [x for x in keys if x[0]==valin or x[1]==valout]
shared_val_from_vals = [x[1] for x in nin_out for y in nin_out if x[1]==y[0]][0]

Change the first column of the matrix from another specified matrix

I have 2 matrices
x = [[1,2,3],
[4,5,6],
[7,8,9]]
y = [0,2,4]
and i want to change each first element from each row of matrix x using each element from matrix y so the end result would be
x = [[0,2,3],
[2,5,6],
[4,8,9]]
i have tried this code
x = [[1,2,3],[4,5,6],[7,8,9]]
y = [0,2,4]
for i in range (len(x)):
x[i][0] = y[0][i]
print (x)
but it only returns "TypeError: 'int' object is not subscriptable"
are there any ways to fix this and how do you expand this so that it's appliable to any n*n matrix?
Change x[i][0] = y[0][i] to x[i][0] = y[i].
Another way to do this with fewer indices:
x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
y = [0, 2, 4]
for x_row, y_int in zip(x, y):
x_row[0] = y_int
print(x)
You do not have matrices. x is a list of lists and y is a list. They can represent matrices/vectors/etc., but those are ultimately mathematical abstractions, which can be implemented in code in different ways.
The first way to do it, maintaining the structure of your code, requires taking note of the above fact: as y is a list containing ints, y[0][i] will clearly not work, since y[0] will always be an int, and you cannot further apply the subscript operator to ints.
Accordingly, this will work:
for i in range (len(x)):
x[i][0] = y[i]
That said, that is not the only way to do it. If you desired a more functional approach, you could do something like this list comprehension:
[[y_value, *x_value[1:]] for x_value, y_value in zip(x, y)]
This gives the same result, but approaches the problem in a more abstract way: the new list will itself contain lists where the first element comes from y and the rest from x. Understanding this, we can instead compose an inner list following this pattern.
zip creates an iterator of pairs of values from x and y. Using this iterator, each value from y can be positioned before each value from x in a list. Lastly, since x_value is a list, it must be unpacked so we get, for example, [0, 2, 4] instead of [0, [2, 4]].
With Python, you would typically avoid using indexes when possible. Since a "matrix" is actually a list of lists, going through rows returns lists which are object references that you can manipulate directly:
for row,value in zip(x,y): row[0] = value

Modifying lists in a Python matrix algorithm

I am working through some algorithm challenges to get some more Python practice. I am having some problems with a problem that requires changing values inside a python matrix (list of lists).
# Challenge
# After they became famous, the CodeBots all decided to move to a new building and live together. The building is represented by a
# rectangular matrix of rooms. Each cell in the matrix contains an integer that represents the price of the room. Some rooms are
# free (their cost is 0), but that's probably because they are haunted, so all the bots are afraid of them. That is why any room
# that is free or is located anywhere below a free room in the same column is not considered suitable for the bots to live in.
# ex: matrix = [[0, 1, 1, 2], [[x, 1, 1, 2],
# [0, 5, 0, 0], --> [x, 5, x, x], --> 5 + 1 + 1 + 2 = 9
# [2, 0, 3, 3]] [x, x, x, x]]
My approach is two-fold: 1) first find all zeros in the matrix and replace that value with 'x'. 2) Once that happens, loop through all the lists and find the index of existing 'x', then use that index value and search for it in the other lists.. replace the numeric value with 'x' if that number is 'below' the existing 'x'.. hopefully that makes sense. I have the first part down and I have attempted the second piece a number of different ways but now am running into an error.. I feel like i'm very close. I also feel like my code is pretty inefficient (I am new to Python), so if there is some far more efficient way to do it please let me know.
I understand what the error means but I am having a hard time fixing it while getting the correct answer..The error is that the index is out of range.
My code:
def matrixElementsSum(matrix):
numList = len(matrix) # essentially the number of 'rows' -> number of lists
numCol = len(matrix[0]) # number of values in each list
# replace 0's in each list with 'x'
for x in matrix:
if x.count(0) > 0:
for index, i in enumerate(x):
if i == 0:
x[index] = 'x'
for x in matrix:
for y in matrix[x]:
if(matrix[x][y] == 'x'):
x_ind = y
for z in matrix:
if(z < x):
matrix[z][x_ind] = 'x'
print(matrix)
Test scenario:
matrixElementsSum([[0, 1, 1, 2],
[0, 5, 0, 0],
[2, 0, 3, 3]])
You are still going to require nested for loops in some fashion or another since you are iterating over a list of lists, but you could simplify the logic a bit using list comprehensions.
def solver(matrix):
mx = [[v if v else 'x' for v in row] for row in matrix]
mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]
return mx[:1] + mxx
I first iterate over the matrix, and replace '0's with "x"s in the new matrix mx.
mx = [[v if v else 'x' for v in row] for row in matrix]
This is just a nested list comprehension, where we operate on each element per row, for every row per matrix. The ... if ... else ... is just your classic ternary operator. If v holds (is not zero in our case), then it evaluates to the value before the "if", otherwise it evaluates to the value after the "else" - in this case 'x'.
I then repeat the process, but offsetting the rows by one so that I can check if the above element is now an "x".
mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]
There's a bit to break down here. Lets start from the "outside" and work our way in.
... for row1, row2 in zip(mx[1:], matrix)
This zips the new matrix, offset by one (using [1:] slice notation), with the original matrix. So it returns an iterable functionally equivalent to the following list:
[(mx_row1, matrix_row0), (mx_row2, matrix_row1), (mx_row3, matrix_row2), ...]
This allows us to extract a given row and the row above it simultaneously, as row1 and row2. Then the other half-
[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)]
-repeats a similar process on each element per row, rather than row per matrix. We do not offset the elements in either row like we offset the rows of the mx matrix, but otherwise the logic is identical. We then again compare with our ternary operator to see if the above element is a 0, and if so evaluate to 'x'. We could easily have changed this to compare each element of each row of mx to 'x' instead of matrix to 0, but I decided to mirror the first list comprehension.
Once I have this new matrix mxx, I simply prepend the first row of mx, because we effectively skip that row when we offset our comparison. The result is a matrix with all 0s and elements below replaced with "x"s.
As per clarification in the comments, if you wish you to mark an "x" if any of the above elements are 0, not just the one directly above, you can accomplish this by taking a slice of that column of the matrix and using the all() builtin to see if any are 0. Revised code below
def solver(matrix):
return [[v if all(col) else 'x' for v, col in zip(row, zip(*matrix[:idx]))] for idx, row in enumerate(matrix, 1)]

counting up smaller numbers in python

i am trying to write a code as part of a simulator that will read a list of numbers and compare them to a secondary list of numbers and tell you how many numbers there are that are less then the first number. for example
X=[5,20,14,1,7]
Y=[2,12,9,5,4,6]
the code will take the first X value 5 and see how many of the Y values are less then 5. so the output Z would look something like
Z=[2,6,6,0,4]
i am not very familiar with these concepts at all, i am wondering how i would go about making a function for this type of work. how would i make a for loop that would go through and compare the numbers like that? also is it possible to combine and sort the lists from smallest to largest and then just search that list for the X value and print its position in the list?
Something like:
[len(list(filter(lambda k: k<m, Y))) for m in X]
You can do it using map and list comprehension in one line:
first = [5, 20, 14, 1, 7]
second = [2, 12, 9, 5, 4, 6]
z = map(lambda x: len([y for y in second if x > y]), first)
or without lambda (as #RobertB wrote):
z = [sum([x > y for y in second]) for x in first]
Result is:
[2, 6, 6, 0, 4]
There are many ways to go about the above question. I will explain the easiest method, although it is not the most efficient method
Concept: Nested For Loop
for x in range (0, a1_len-1):
for y in range (0, a2_len -1):
if a[y] < a[x]:
new_array.append(a[y])
print (new_array)
Hope this helps
Another answer using broadcasting with numpy:
import numpy as np
np.apply_along_axis(np.sum,0,np.array(Y).reshape((len(Y),1))<X)

Deleting elements in a row

I want to get an answer for c where c is defined as:
c= x+y
I have the following entry for x and y:
x y
-2 5
-3 10
2 15
4 20
6 25
to get the data, I loaded it from a csv file:
data=np.loadtxt('data.csv',delimiter=',',skiprows=1)
x_value= data[:,0]
y_value= data[:,1]
The code works fine until I decided to remove the negative entry for x. I have:
x_value1= [x for x in x_value if float(x)>0]
It now returns an error. I understand that for it to work, I also have to remove 5 and 10 in y since the entries for the equation are not the same. I don't have any idea how should I do it.
You're probably going to want to ditch the list comprehension for this, since it's a longer operation and it will involve multiple lists. You could just use indices, and copy the non-negative data into new lists:
new_x = []
new_y = []
for i in range(len(x)):
if x[i] >= 0:
new_x.append(x[i])
new_y.append(y[i])
Alternate strategy using zip:
new_x = []
new_y = []
for x_elem, y_elem in zip(x,y):
if x_elem >= 0:
new_x.append(x_elem)
new_y.append(y_elem)
I'm not sure if there's a more condensed way of doing this, but I prefer longer, more readable code anyway.
Use your logic on data instead, checking for negative on the first entry of each 2-tuple:
>>> data
array([[-2, 5],
[-3, 10],
[ 2, 15],
[ 4, 20],
[ 6, 25]])
>>> data2 = n.array([x for x in data if float(x[0])>0]) # x here is each row
>>> data2
array([[ 2, 15],
[ 4, 20],
[ 6, 25]])
Probably you can try something like:
data[data[:,0]>0]
as hinted in the similar answer:filtering lines in a numpy array according to values in a range

Categories

Resources