I am using Python 3.8.
The following list contains integers and I need to generate a hierarchy from this list:
list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]
I need this result (output could be a list, e.g. [[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]):
1 ---- 15 ---- 121 ---- 155
\---- 22 ---- 101
\--- 23 ---- 105
\----- 106
\---- 108 ---- 120
2 ---- 19
5 ---- 25 ---- 28 ----- 29
8 ---- 33
\---- 35
The hierarchy does not contain any duplicated items. Also first items of the lists in the list1 do not contain repeated/duplicated elements, but second items of the lists in the list1 contain.
How could this hierarchy be generated?
Note: I could do this by using some code but it could be very long and CPU cost could be high (actual list is very long).
You can try using this recursive function, it is a bit verbose and can be re written using list comprehensions. need is your expected output.
list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]
need = [[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]
graph = {}
for y, x in list1:
graph.setdefault(x, []).append(y)
def form_graph(graph):
seen = set()
def form(k, v):
if k in seen:
return []
res = [[k]]
res[-1].extend(v)
seen.add(k)
for i in v:
if i in graph:
res.extend(form(i, graph[i]))
return res
result = []
for k, v in graph.items():
temp = form(k, v)
if temp:
if len(temp) == 1:
temp = temp[0]
result.append(temp)
return result
Output
print(form_graph(graph))
[[[1, 15, 22, 23], [15, 121], [121, 155], [22, 101], [23, 105, 106, 108], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]
print(need == form_graph(graph))
True
Upvote and accept the answer if you find this useful.
You can use a breadth-first search:
from collections import deque, defaultdict
list1 = [[15, 1], [22, 1], [23, 1], [121, 15], [101, 22], [105, 23], [106, 23], [108, 23], [155, 121], [120, 108], [19, 2], [25, 5], [33, 8], [35, 8], [28, 25], [29, 28]]
def get_levels():
q, r, d = deque(sorted({(b, b) for a, b in list1 if all(k != b for k, _ in list1)})), [], defaultdict(list)
while q:
r.append(((n:=q.popleft())[0], [n[-1], *(l:=[a for a, b in list1 if b == n[-1]])]))
q.extend([(n[0], i) for i in l])
for a, b in r:
if len(b) > 1:
d[a].append(b)
return [i for b in d.values() for i in ([b] if len(b) > 1 else b)]
print(get_levels())
Output:
[[[1, 15, 22, 23], [15, 121], [22, 101], [23, 105, 106, 108], [121, 155], [108, 120]], [2, 19], [[5, 25], [25, 28], [28, 29]], [8, 33, 35]]
I have been reading a lot of similar posts like here, here, here, and so on, yet I am not able to fix my problem. I need the colormap for my scatter plot to be effective on both axes, yet it can work on one axis only (in my example, axis "x"):
my_list = [[73, 84], [69, 84], [66, 84], [76, 83], [73, 83], [62, 84], [62, 83], [73, 79], [61, 84], [61, 83], [60, 90], [62, 79], [58, 84], [57, 90], [61, 79], [60, 79], [57, 84], [58, 83], [55, 84], [59, 79], [57, 83], [58, 79], [50, 84], [55, 83], [48, 84], [57, 79], [47, 84], [55, 79], [46, 93], [73, 78], [46, 84], [50, 83], [54, 79], [61, 78], [45, 88], [50, 79], [45, 84], [58, 78], [47, 83], [48, 79], [57, 78], [62, 20], [44, 84], [46, 83], [47, 79], [55, 78], [60, 20], [43, 84], [44, 83], [41, 84], [58, 20], [46, 79], [55, 25], [70, 15], [38, 95], [43, 83], [40, 84], [38, 89], [57, 20], [44, 79], [55, 24], [65, 15], [34, 100], [55, 20], [62, 19], [43, 79], [38, 84], [54, 24], [50, 78], [34, 95], [65, 13], [41, 83], [62, 13], [37, 84], [42, 79], [60, 19], [54, 20], [51, 24], [49, 78], [65, 10], [34, 90], [41, 79], [35, 84], [40, 83], [60, 15], [57, 19], [45, 78], [51, 20], [34, 88], [62, 10], [54, 19], [57, 15], [40, 79], [44, 78], [50, 20], [60, 10], [34, 84], [51, 19], [39, 79], [57, 10], [49, 20], [43, 78], [65, 8], [33, 84], [31, 88], [35, 83], [32, 84], [36, 79], [52, 15], [41, 78], [55, 10], [49, 19], [46, 74], [62, 8], [30, 90], [31, 84], [33, 83], [35, 79], [38, 78], [54, 10], [49, 15], [44, 74], [30, 88], [60, 8], [47, 19], [30, 84], [31, 83], [46, 20], [48, 15], [33, 79], [51, 10], [37, 78], [43, 25], [58, 8], [29, 90], [46, 19], [30, 83], [45, 20], [31, 79], [47, 15], [34, 78], [50, 10], [43, 24], [41, 74], [29, 84], [57, 8], [30, 79], [31, 78], [46, 15], [49, 10], [43, 20], [38, 24], [37, 74], [54, 8], [29, 83], [29, 79], [26, 84], [39, 20], [48, 10], [43, 15], [30, 78], [37, 24], [51, 8], [25, 90], [26, 83], [45, 10], [29, 78], [42, 15], [34, 74], [37, 20], [50, 8], [25, 84], [43, 13], [26, 79], [42, 14], [40, 15], [39, 19], [35, 20], [44, 10], [27, 78], [34, 24], [25, 83], [49, 8], [35, 19], [25, 79], [26, 78], [37, 15], [40, 13], [43, 10], [34, 20], [30, 74], [22, 84], [47, 8], [23, 79], [22, 83], [25, 78], [35, 15], [39, 10], [34, 19], [29, 74], [46, 8], [19, 90], [23, 78], [34, 15], [22, 79], [37, 10], [45, 8], [33, 20], [26, 74], [54, 5], [19, 88], [20, 79], [33, 19], [34, 14], [30, 20], [36, 10], [44, 8], [22, 78], [26, 25], [51, 5], [19, 84], [34, 13], [19, 79], [18, 84], [29, 20], [30, 19], [33, 15], [20, 78], [35, 10], [43, 8], [26, 24], [25, 74], [17, 88], [49, 5], [29, 19], [18, 79], [26, 20], [30, 15], [34, 10], [39, 8], [19, 78], [23, 24], [48, 5], [15, 88], [34, 9], [33, 10], [30, 14], [26, 15], [35, 8], [18, 78], [23, 20], [22, 74], [15, 84], [43, 5], [15, 83], [17, 78], [34, 8], [31, 10], [26, 14], [19, 74], [22, 20], [14, 84], [39, 5], [15, 79], [16, 78], [29, 10], [31, 8], [26, 13], [18, 74], [21, 20], [38, 5], [14, 83], [15, 78], [21, 19], [14, 79], [23, 15], [30, 8], [26, 10], [16, 74], [19, 20], [33, 5], [11, 84], [26, 9], [12, 79], [14, 78], [25, 10], [27, 8], [22, 15], [15, 74], [19, 19], [31, 5], [11, 83], [18, 19], [12, 78], [25, 8], [23, 10], [19, 15], [22, 14], [17, 20], [14, 74], [26, 5], [11, 79], [18, 15], [23, 9], [22, 10], [19, 14], [17, 19], [12, 74], [25, 5], [11, 78], [18, 14], [19, 10], [22, 9], [17, 15], [23, 5], [14, 20], [11, 74], [43, 3], [18, 10], [20, 9], [17, 14], [14, 19], [22, 5], [11, 24], [31, 3], [18, 8], [15, 14], [17, 10], [14, 15], [19, 5], [25, 3], [11, 20], [26, 0], [10, 78], [13, 15], [15, 10], [22, 3], [17, 5], [11, 19], [10, 74], [7, 84], [23, 0], [15, 8], [14, 10], [16, 5], [20, 3], [8, 74], [11, 15], [7, 78], [22, 0], [15, 5], [14, 8], [17, 3], [11, 13], [10, 20], [7, 74], [20, 0], [4, 79], [10, 15], [11, 10], [16, 3], [14, 5], [5, 78], [7, 20], [3, 88], [19, 0], [10, 14], [9, 15], [11, 9], [14, 3], [4, 78], [7, 19], [3, 79], [17, 0], [12, 5], [11, 8], [13, 3], [10, 10], [4, 74], [7, 15], [3, 78], [15, 0], [12, 3], [11, 5], [9, 10], [7, 14], [14, 0], [3, 20], [11, 3], [10, 5], [9, 9], [7, 10], [3, 19], [12, 0], [5, 10], [9, 5], [3, 15], [11, 0], [3, 14], [9, 3], [4, 10], [2, 19], [0, 84], [10, 0], [3, 10], [7, 8], [1, 78], [2, 14], [0, 79], [9, 0], [1, 74], [2, 10], [7, 0], [0, 78], [4, 5], [1, 10], [0, 74], [5, 0], [1, 8], [3, 5], [4, 0], [0, 10], [2, 3], [3, 0], [0, 8], [1, 3], [2, 0], [0, 5], [1, 0], [0, 3], [0, 0]]
x = [x[0] for x in my_list]
y = [x[1] for x in my_list]
plt.scatter(x, y, c=x, cmap='RdYlBu')
plt.colorbar()
As you see, the color map is working on "x" axis only. Now if I change my axis to "y", then this is what I would get:
What I need is a combination of these two .. that the color changes from red to blue from 0 to 100 on both axes. I have tried different ways and even different plots like imshow or heatmap, but scatter is what I need and I keep getting different errors. Could anyone help me to fix this please?
To color code based on both x and y values, one method is to use their vector sum (or distance from origin). First, you define the distance for each point. Then use that distance for color coding:
import numpy as np
d = [np.sqrt(i**2 + j**2) for i, j in zip(x, y)]
plt.scatter(x, y, c=d, cmap='RdYlBu')
plt.colorbar()