Related
I am reforming the 2D coordinate number in a aligned way which was not aligned (coordinate numbers were suffled) before.
I have below input coordinates,
X = [2, 2, 3, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 5, 4, 3, 5, 5, 5]
Y = [2, 3, 3, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 2, 2, 2, 3, 4, 5]
I have to make it aligned. Therefore, I first applied Sorted function on this coordinates. I got below output after it.
merged_list1 = sorted(zip(X, Y))
output
X1_coordinate_reformed = [2, 2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6]
Y1_coordinate_reformed = [2, 3, 2, 3, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6]
Still it iot aligned properly. I want two consecutive nodes place next to each other. Therefore I am applying the approach to find the nearest coordinate from origin to find the very first node. Then from the first node, I found another nearest coordinate and so on...For that, I have applied below code,
First I wrote a function which calculates the distance and gives index of the nearest coordinate from the list.
def solve(pts, pt):
x, y = pt
idx = -1
smallest = float("inf")
for p in pts:
if p[0] == x or p[1] == y:
dist = abs(x - p[0]) + abs(y - p[1])
if dist < smallest:
idx = pts.index(p)
smallest = dist
elif dist == smallest:
if pts.index(p) < idx:
idx = pts.index(p)
smallest = dist
return idx
coor2 = list(zip(X1_coordinate_reformed, Y1_coordinate_reformed)) # make a list which contains tuples of X and Y coordinates
pts2 = coor2.copy()
origin1 = (0, 0)
new_coor1 = []
for i in range(len(pts2)):
pt = origin1
index_num1 = solve(pts2, pt)
print('index is', index_num1)
origin1 = pts2[index_num1]
new_coor1.append(pts2[index_num1])
del pts2[index_num1]
After running the code, I got below output,
[(6, 6), (5, 6), (4, 6), (4, 5), (4, 4), (4, 3), (3, 3), (2, 3), (2, 2), (3, 2), (4, 2), (5, 2), (5, 3), (5, 4), (5, 5), (6, 5), (6, 4), (6, 3), (6, 2)]
Which is not correct because it can be clearly understand that,
coor2 = [(2, 2), (2, 3), (3, 2), (3, 3), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]
origin = (0, 0)
if we find the distance between Origin which was (0, 0) in very first and from every coordinate from above coor2 list, we will get (2,2) is nearest coordinate. Then How come my code gives (6,6) is the nearest coordinate??
The interesting thing is, if I apply the same procedure (sorting followed by finding nearest coordinate) on below coordinates,
X2_coordinate = [2, 4, 4, 2, 3, 2, 4, 3, 1, 3, 4, 3, 1, 2, 0, 3, 4, 2, 0]
Y2_coordinate = [3, 4, 2, 1, 3, 2, 1, 0, 0, 2, 3, 4, 1, 4, 0, 1, 0, 0, 1]
After applying sorted function
X2_coordinate_reformed = [0, 0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]
Y2_coordinate_reformed = [0, 1, 0, 1, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
After applying method of searching nearest coordinates mentioned above, the result I got
[(0, 0), (0, 1), (1, 1), (1, 0), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 4), (3, 3), (3, 2), (3, 1), (3, 0), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
Kindly suggest me where I am doing wrong and what should I change??
It is better to use scipy for finding closest coordinate.
The code given below works.
from scipy import spatial
pts = merged_list1.copy()
origin = (0, 0)
origin = np.array(origin)
new_coordi = []
for i in range(len(pts)):
x = origin
distance,index = spatial.KDTree(pts).query(x)
new_coordi.append(pts[index])
origin = np.array(pts[index])
del pts[index]
I need to concatenate a uid from uids column to each of the uids in the list of the friends column, as shown in the following example:
Given a pandas.DataFrame object A:
uid friends
0 1 [10, 2, 1, 5]
1 2 [1, 2]
2 3 [5, 4]
3 4 [10, 5]
4 5 [1, 2, 5]
the desired output is:
uid friends in_edges
0 1 [10, 2, 1, 5] [(1, 10), (1, 2), (1, 1), (1, 5)]
1 2 [1, 2] [(2, 1), (2, 2)]
2 3 [5, 4] [(3, 5), (3, 4)]
3 4 [10, 5] [(4, 10), (4, 5)]
4 5 [1, 2, 5] [(5, 1), (5, 2), (5, 5)]
I use the following code to achieve this outcome:
import numpy as np
import pandas as pd
A = pd.DataFrame(dict(uid=[1, 2, 3, 4, 5], friends=[[10, 2, 1, 5], [1, 2], [5, 4], [10, 5], [1, 2, 5]]))
A.loc[:, 'in_edges'] = A.loc[:, 'uid'].apply(lambda uid: [(uid, f) for f in A.loc[A.loc[:, 'uid']==uid, 'friends'].values[0]])
but it the A.loc[A.loc[:, 'uid']==uid, 'friends'] part looks kind of cumbersome to me, so I wondered if there is an easier way to accomplish this task?
Thanks in advance.
You can use .apply() with axis=1 parameter:
df["in_edges"] = df[["uid", "friends"]].apply(
lambda x: [(x["uid"], f) for f in x["friends"]], axis=1
)
print(df)
Prints:
uid friends in_edges
0 1 [10, 2, 1, 5] [(1, 10), (1, 2), (1, 1), (1, 5)]
1 2 [1, 2] [(2, 1), (2, 2)]
2 3 [5, 4] [(3, 5), (3, 4)]
3 4 [10, 5] [(4, 10), (4, 5)]
4 5 [1, 2, 5] [(5, 1), (5, 2), (5, 5)]
Why not try product
import itertools
A['in_edges'] = A.apply(lambda x : [*itertools.product([x['uid']], x['friends'])],axis=1)
A
Out[50]:
uid friends in_edges
0 1 [10, 2, 1, 5] [(1, 10), (1, 2), (1, 1), (1, 5)]
1 2 [1, 2] [(2, 1), (2, 2)]
2 3 [5, 4] [(3, 5), (3, 4)]
3 4 [10, 5] [(4, 10), (4, 5)]
4 5 [1, 2, 5] [(5, 1), (5, 2), (5, 5)]
The list that I have:
a = [1,2,3]
The output that I want:
combinations = [11, 12, 13, 21, 22, 23, 31, 32, 33]
I have tried:
a = [1,2,3]
all_combinations = []
list1_permutations = itertools.permutations(a, len(a))
for each_permutation in list1_permutations:
zipped = zip(each_permutation, a)
all_combinations.append(list(zipped))
print(all_combinations)
But I am getting the output like:
[[(1, 1), (2, 2), (3, 3)], [(1, 1), (3, 2), (2, 3)], [(2, 1), (1, 2), (3, 3)], [(2, 1), (3, 2), (1, 3)], [(3, 1), (1, 2), (2, 3)], [(3, 1), (2, 2), (1, 3)]]
This might be easiest with a nested list comprehension:
a = [1, 2, 3]
out = [int(f'{i}{j}') for i in a for j in a]
print(out)
Output:
[11, 12, 13, 21, 22, 23, 31, 32, 33]
The same result can be achieved (perhaps more efficiently) with itertools.product:
import itertools
a = [1, 2, 3]
out = [int(f"{a}{b}") for a, b in itertools.product(a, a)]
This should work.
you can use a list comprehension to make all combos because you appear to want to sample with duplicates like '33'
you can use a list gen to do this
you need to treat the items like strings to join them
you need to convert it back to integer if that is what you want as final result
a=[1,2,3]
result = [int(''.join([str(i), str(j)])) for i in a for j in a]
print(result)
I am working on weighted graphs and I would like to assign a random weight for the edges of the graph, such that,
weight of edge(a, a) = 0
weight of (a, b) = weight of edge(b, a) = K
where K is some random number. This goes on for all the edges of the graphs.
For that, I am using random.randint() method. I am actually using the logic of sum. If sum of both the edges is same, then assign some random integer.
Here is my code,
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if i == j:
edgelist.append((i, j, 0))
if (i != j and sum((i, j)) == sum((j, i))):
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
print(edgelist)
Actual result,
[(1, 1, 0), (1, 2, 18), (1, 3, 6), (2, 1, 13), (2, 2, 0), (2, 3, 21), (3, 1, 20), (3, 2, 17), (3, 3, 0)]
Expected result,
[(1, 1, 0), (1, 2, K), (1, 3, H), (2, 1, K), (2, 2, 0), (2, 3, P), (3, 1, H), (3, 2, P), (3, 3, 0)]
where, K, H, P are some random integers.
If the ordering of the result is not important following code gives the desired output:
import random
num_nodes = 3
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if j > i:
break
if i == j:
edgelist.append((i, j, 0))
else:
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
edgelist.append((j, i, rand))
print(edgelist)
# [(1, 1, 0), (2, 1, 7), (1, 2, 7), (2, 2, 0), (3, 1, 18), (1, 3, 18), (3, 2, 13), (2, 3, 13), (3, 3, 0)]
In case you need the edges sorted, simply use:
print(sorted(edgelist))
# [(1, 1, 0), (1, 2, 20), (1, 3, 16), (2, 1, 20), (2, 2, 0), (2, 3, 23), (3, 1, 16), (3, 2, 23), (3, 3, 0)]
Just a little change in your code will do the trick.
Here is the solution I found to obtain your expected output
num_nodes = 3
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if i == j:
edgelist.append((i, j, 0))
elif i < j:
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
edgelist.append((j, i, rand))
print(sorted(edgelist))
This code outputs :
[(1, 1, 0), (1, 2, 15), (1, 3, 15), (2, 1, 15), (2, 2, 0), (2, 3, 21), (3, 1, 15), (3, 2, 21), (3, 3, 0)]
So I figured out something interesting. Say below matrix shows edges in a complete graph of 5 nodes,
[1, 1] [1, 2] [1, 3] [1, 4] [1, 5]
[2, 1] [2, 2] [2, 3] [2, 4] [2, 5]
[3, 1] [3, 2] [3, 3] [3, 4] [3, 5]
[4, 1] [4, 2] [4, 3] [4, 4] [4, 5]
[5, 1] [5, 2] [5, 3] [5, 4] [5, 5]
now, moving right side from principal diagonal, we have lists whose first element is less than second element. We just got to target them and append new random weight to it.
Here is my code,
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
edgelist.append([i, j])
p = 0
eff_edgelist = []
while p < len(edgelist):
if edgelist[p][0] <= edgelist[p][1]:
eff_edgelist.append(edgelist[p])
p += 1
for i in eff_edgelist:
if i[0] == i[1]:
i.append(0)
else:
i.append(random.randint(5, 50))
eff_edgelist = [tuple(i) for i in eff_edgelist]
for i in list(G.edges(data=True)):
print([i])
and the result,
[(1, 1, {'weight': 0})]
[(1, 2, {'weight': 12})]
[(1, 3, {'weight': 37})]
[(1, 4, {'weight': 38})]
[(1, 5, {'weight': 6})]
[(2, 2, {'weight': 0})]
[(2, 3, {'weight': 12})]
[(2, 4, {'weight': 40})]
[(2, 5, {'weight': 8})]
[(3, 3, {'weight': 0})]
[(3, 4, {'weight': 15})]
[(3, 5, {'weight': 38})]
[(4, 4, {'weight': 0})]
[(4, 5, {'weight': 41})]
[(5, 5, {'weight': 0})]
and if you check, print(G[2][1]), the output will be {'weight': 12},
which means weight of edge(a, b) = weight of edge(b, a).
In Python is there a way to get all 3 pairs or n pairs of a list from a list?
For example list = [1,2,3,4]
result : [[1,2,3],[2,3,4],[1,2,4]]
I want to find all possible n pairs of lists from a Python list. I do not want to import any other functions like itertools.
You can use the module itertools. It comes inside Python by default (you don't need to install it throught third party modules):
>>> import itertools
>>> print(itertools.permutations([1,2,3,4], 3))
[(1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 4), (1, 4, 2), (1, 4, 3), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 3, 4), (2, 4, 1), (2, 4, 3), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 2, 4), (3, 4, 1), (3, 4, 2), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 2, 3), (4, 3, 1), (4, 3, 2)]
This itertools.permutations(iterable, r=None) produces all the possible permutations of a given iterable element (like a list). If r is not specified or is None, then r defaults to the length of the iterable and all possible full-length permutations are generated.
If you are looking only for n pair of permutations instead of all the possible permutations just delete the rest of them:
>>> print(list(itertools.permutations([1,2,3,4], 3))[:3])
[(1, 2, 3), (1, 2, 4), (1, 3, 2)]
As you asked in comments you can do that without importing any module. itertools.permutations is just a function, which you can make by yourself:
def permutations(iterable, r=None):
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
But I strongly advise your importing it. If you don't want to import the whole module, just this function simply do from itertools import permutations.