I want to set the colour for specific nodes in networkx lib with Python.
These are my nodes:
node_list = ["A", "B", "C", "D", "E", "F"]
And these are the colours that I want:
A->red
B->red
C->red
D->green
E->green
F->blue
I do not know how to do this, because sometimes i have more than 200 different nodes so i am looking for some solution that will work with dict:
{"red":[A,B,C], "green": [D,E], "blue": [F]}
This is my code:
import networkx as nx
analysis_graph = nx.Graph()
node_list = ["A", "B", "C", "D", "E", "F"]
analysis_graph.add_nodes_from(node_list)
#print(analysis_graph.nodes())
nx.draw(analysis_graph, with_labels = True)
relation_list = [['A', 'B'],
['A', 'C'],
['B', 'D'],
['C', 'E'],
['D', 'F'],
['E', 'D'],
['C', 'E'],
['B', 'D'],
['C', 'F'],
['A', 'E'],
['B', 'C'],
['B', 'F'],
['D', 'A']]
analysis_graph = nx.from_edgelist(relation_list)
print(nx.info(analysis_graph))
nx.draw(analysis_graph, with_labels = True)
Sure. According to the docs nx.draw supports a node_color argument. You'll just have to explicitly list the nodes in a proper order:
relation_list = [
["A", "B"],
["A", "C"],
["B", "D"],
["C", "E"],
["D", "F"],
["E", "D"],
["C", "E"],
["B", "D"],
["C", "F"],
["A", "E"],
["B", "C"],
["B", "F"],
["D", "A"],
]
colors = {"red": ["A", "B", "C"], "green": ["D", "E"], "blue": ["F"]}
analysis_graph = nx.from_edgelist(relation_list)
# Create a mapping of node -> color from `colors`:
node_color_map = {}
for color, nodes in colors.items():
node_color_map.update(dict.fromkeys(nodes, color))
# Create a list of all the nodes to draw
node_list = sorted(nx.nodes(analysis_graph))
# ... and a list of colors in the proper order.
node_color_list = [node_color_map.get(node) for node in node_list]
# Draw the graph with the correct colors.
nx.draw(
analysis_graph,
with_labels=True,
nodelist=node_list,
node_color=node_color_list,
)
The output is e.g.
Related
Given a list of length 2n, say ["a", "b", "c", "d", "e", "f"] or ["a", "a", "b", "b", "c", "d"] (elements in the list don't necessarily have to be unique), I'd like to generate all the possible distinct permutations of that list while taking into account that the order in which the element 2k and the element 2k+1 appear doesn't matter. That means that
["a", "b", "c", "d", "e", "f"] and ["b", "a", "c", "d", "e", "f"] are the same permutation, but
["a", "b", "c", "d", "e", "f"] and ["a", "c", "b", "d", "e", "f"] are not.
For example, from the list ["a", "b", "c", "d"], the code I need would generate this sequence:
["a", "b", "c", "d"], ["a", "c", "b", "d"], ["a", "d", "b", "c"], ["b", "c", "a", "d"], ["b", "d", "a", "c"], ["c", "d", "a", "b"]
I know it's possible to do that by generating all the permutations and keeping one of each of those that are equivalent to each other, but that's not a very efficient way to proceed, especially with larger sets. Is there a more efficient way to do that?
I wrote this code, but it's highly inefficient (keep in mind that I need to use lists with a length of up to 14):
from itertools import permutations
list_letters = ["a", "b", "c", "d"]
n = int(len(list_letters) / 2)
set_distinct_perm = set()
for perm in permutations(list_letters):
perm = list(perm)
for i in range(n):
perm[2*i:2*i + 2] = sorted(perm[2*i:2*i+2])
perm = tuple(perm)
set_distinct_perm.add(perm)
print(set_distinct_perm)
How about the following, where we take permutations of each [2k, 2k+1] (inclusive) subsequence and then take the product of those permutations:
from itertools import product, permutations
def equivalents(lst):
perms = product(*({*permutations(lst[i:i+2])} for i in range(0, len(lst), 2)))
return [[x for tupl in perm for x in tupl] for perm in perms] # flattening inner part
print(*equivalents('abcdef'))
# ['a', 'b', 'c', 'd', 'f', 'e'] ['b', 'a', 'c', 'd', 'f', 'e']
# ['a', 'b', 'c', 'd', 'e', 'f'] ['a', 'b', 'd', 'c', 'f', 'e']
# ['a', 'b', 'd', 'c', 'e', 'f'] ['b', 'a', 'd', 'c', 'e', 'f']
# ['b', 'a', 'd', 'c', 'f', 'e'] ['b', 'a', 'c', 'd', 'e', 'f']
print(*equivalents('aabbef'))
# ['a', 'a', 'b', 'b', 'f', 'e'] ['a', 'a', 'b', 'b', 'e', 'f']
So I want to loop through a list starting at string "B" to the end or until a new "B" is reached and so on till the end of the list.
l=["A", "B", "C", "D", "B", "M", "C", "T", "B", "g", "do"]
index = [idx for idx, s in enumerate(l) if 'B' in s]
print(index)
I want to loop through the list so I get these outputs but without hard coding the indices:
l[1:4]=['B', 'C', 'D']
l[4:8]=['B', 'M', 'C', 'T']
l[8:]=['B', 'g', 'do']
If just one index has that string then
l=["A", "B", "C", "D"]
index = [idx for idx, s in enumerate(l) if 'B' in s]
print(index)
l[1:]=["B", "C", "D"]
Taking your code and using a for loop:
l = ["A", "B", "C", "D", "B", "M", "C", "T", "B", "g", "do"]
index = [idx for idx, s in enumerate(l) if 'B' in s]
out_of_bounds_index = len(index)
result = []
for i in range(out_of_bounds_index):
if i+1 < out_of_bounds_index:
result.append(l[index[i]:index[i+1]])
else:
result.append(l[index[i]:])
print(result)
Or a list comprehension:
l = ["A", "B", "C", "D", "B", "M", "C", "T", "B", "g", "do"]
index = [idx for idx, s in enumerate(l) if 'B' in s]
out_of_bounds_index = len(index)
result = [l[index[i]:index[i+1]]
if i+1 < out_of_bounds_index
else l[index[i]:]
for i in range(out_of_bounds_index)]
print(result)
Output:
[['B', 'C', 'D'], ['B', 'M', 'C', 'T'], ['B', 'g', 'do']]
Try this:
def get_lists(l):
indices = [i for i, x in enumerate(l) if x == "B"]
if len(indices) == 0:
return []
elif len(indices) == 1:
return [[l[indices[0]]]]
else:
result = list()
for i in range(len(indices)):
if indices[i] == indices[-1]:
result.append(l[indices[i]:])
else:
result.append(l[indices[i]:indices[i+1]])
return result
k = ["A", "B", "C", "D", "B", "M", "C", "T", "B", "g", "do"]
print(get_lists(k))
Output:
[['B', 'C', 'D'], ['B', 'M', 'C', 'T'], ['B', 'g', 'do']]
l = ["A", "B", "C", "D", "B", "M", "C", "T", "B", "g", "do"]
#note that an extra 'B' is added to the list: l+['B']
indexOfB = [i for i, x in enumerate(l+['B']) if x == 'B']
Blists = [l[i[0]:i[1]] for i in zip(indexOfB, indexOfB[1:])]
[print(x) for x in Blists]
I am iterating over nested lists with a for-loop and would like to insert a new nested lists at the next index if a condition is met. During the next iterations these newly added lists should be skipped. Example:
input_lst = [["a", "b"], ["a", "d"], ["e", "f"]]
for sublst in input_lst:
if sublst[0] == "a":
new_sublst = []
input_lst.insert((input_lst.index(sublst) + 1), new_sublst)
new_sublst.insert(0, "a")
new_sublst.insert(1, "z")
print(input_lst)
Intended outcome:
[["a", "b"], ["a", "z"], ["a", "d"], ["a", "z"], ["e", "f"]]
Actual outcome - endless loop with:
[["a", "b"], ["a", "z"], ["a", "z"], ["a", "z"], ["a", "z"] ...
Try this :
input_lst = [["a", "b"], ["a", "d"], ["e", "f"]]
result = []
for sublst in input_lst:
result.append(sublst)
if sublst[0] == "a":
result.append(["a", "z"])
print(result)
Alternatively:
input_lst = [["a", "b"], ["a", "d"], ["e", "f"]]
for sublst in input_lst:
if sublst == ["a","z"]:
continue
if sublst[0] == "a":
new_sublst = []
input_lst.insert((input_lst.index(sublst) + 1), new_sublst)
new_sublst.insert(0, "a")
new_sublst.insert(1, "z")
print(input_lst)
Result:
[['a', 'b'], ['a', 'z'], ['a', 'd'], ['a', 'z'], ['e', 'f']]
Point to note:
If you add ["a","z"] as the next element in the list when current sublst start with "a", you created a endless-loop because next iteration is definitely starting with an "a" as in ["a", "z"].
Using a new list to store result of each iteration can solve the problem. Or you can skip adding another ["a","z"] when the current sublst is ["a","z"].
You could use a second list:
input_lst = [["a", "b"], ["a", "d"], ["e", "f"]]
new_sublst = ["a", "z"]
output_lst = []
for sublst in input_lst:
output_lst.append(sublst)
if sublst[0] == "a":
output_lst.append(new_sublst)
Output:
[['a', 'b'], ['a', 'z'], ['a', 'd'], ['a', 'z'], ['e', 'f']]
Adding to the answer of #ytung-dev, which tests against a specific condition, I came up with a solution that uses a second list as a negative to compare against. Maybe someone else will find this useful:
input_lst = [["a", "b"], ["a", "d"], ["e", "f"]]
input_lst_negative = []
for sublst in input_lst:
if (sublst[0] == "a") and (sublst not in input_lst_negative):
new_sublst = []
input_lst.insert((input_lst.index(sublst) + 1), new_sublst)
new_sublst.insert(0, "a")
new_sublst.insert(1, "z")
input_lst_negative.append(new_sublst)
print(input_lst)
Output:
[['a', 'b'], ['a', 'z'], ['a', 'd'], ['a', 'z'], ['e', 'f']]
This question already has answers here:
Mutually exclusive random sampling from a list
(3 answers)
Closed 3 years ago.
I have the following:
list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
for i in range(3):
print(random.sample(list1, k=1))
print(random.sample(list1, k=1))
print(random.sample(list1, k=1))
and am looking for something like:
['a', 'g', 'i']
['c', 'h', 'b']
['k', 'd', 'e']
The idea being to have no repeats anywhere.
I understand that I could slice the list if not using a loop, but am unsure of how to go about it with the loop involved.
Just shuffle it and take subsequent slices:
list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
random.shuffle(list1)
N = 3
for i in range(0, len(list1)-N+1, N):
print(list1[i:i+N])
#['c', 'b', 'd']
#['i', 'e', 'j']
#['h', 'g', 'f']
Shuffle the list then break it apart:
import random
list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
random.shuffle(list1)
for i in range(0, len(list1), 3):
print(list1[i:i+3])
You could also use you're original sample function and slice the list using list comprehensions:
list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
output = random.sample(list1, k=9)
output = [output[i:i+3] for i in range(0,9,3)]
Input:
import random
list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
for i in range(3):
print([list1.pop(random.choice(range(len(list1)))) for i in range(3)])
Output:
['j', 'g', 'b']
['f', 'c', 'h']
['e', 'k', 'i']
>>> list1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
>>> mylist = random.sample(list1, k=9)
>>> print([mylist[i:i+3] for i in range(0, 9, 3)])
output
[['e', 'b', 'i'], ['k', 'h', 'd'], ['j', 'f', 'a']]
So I was wondering whether it's possible to get a sublist of a list into a dictionary.
For example, a list contains:
cy = [["a", "b", "a"], ["a", "b", "c", "d", "a"], ["c", "b", "a", "c"], ["d, "b", "a", "d"]]
would be stored into a dictionary according to the first letter of the sublist
{a : ["a", "b", "a"], c : ["c", "b", "a", "c"], d: ["d, "b", "a", "d"] }
Notice that it only stores the first sublist of the key that starts with the "a" and not the next.
My code is as follows:
def syn(graph,start):
empty = []
cy = [["a", "b", "a"], ["a", "b", "c", "d", "a"], ["c", "b", "a", "c"], ["d, "b", "a", "d"]]
lei = dict()
for items in cy:
if items[0] in lei:
lei[items[0]] += items
else:
lei[items[0]] = items
return lei
But all I get is
{a : ["a", "b", "a"]}
Is there any way to fix this?
With simple dict comprehension:
cy = [["a", "b", "a"], ["a", "b", "c", "d", "a"], ["c", "b", "a", "c"], ["d", "b", "a", "d"]]
result = {l[0]: l[:] for l in cy[::-1]}
print(result)
The output:
{'a': ['a', 'b', 'a'], 'c': ['c', 'b', 'a', 'c'], 'd': ['d', 'b', 'a', 'd']}
cy[::-1] - processing the input list in reversed order to prevent overlapping by same next "keys"
While you can very cleverly iterate backwards, as #juanpa.arrivillaga's and #RomanPerekhrest solutions demonstrate, another approach is to simple iterate over the list and user the any function:
cy = [["a", "b", "a"], ["a", "b", "c", "d", "a"], ["c", "b", "a", "c"], ["d", "b", "a", "d"]]
new_list = []
for i in cy:
if not any(i[0] == b[0] for b in new_list):
new_list.append(i)
final_dict = {i[0]:i for i in new_list}
Output:
{'a': ['a', 'b', 'a'], 'c': ['c', 'b', 'a', 'c'], 'd': ['d', 'b', 'a', 'd']}
The most straightforward way is to iterate over your list backwards, adding the list to the dict based on the first element. Since you go backwards, this guarantees that the first sublist will be the list contained in your dict:
>>> result = {}
>>> for sub in reversed(cy):
... result[sub[0]] = sub
...
>>> result
{'d': ['d', 'b', 'a', 'd'], 'a': ['a', 'b', 'a'], 'c': ['c', 'b', 'a', 'c']}
>>>
So, you would keep the last encountered value, but the last value of list in reverse order is the first value in forward order!
Using pandas:
import pandas as pd
cy = [["a", "b", "a"], ["a", "b", "c", "d", "a"], ["c", "b", "a", "c"], ["d", "b", "a", "d"]]
# create a df
df = pd.DataFrame([[i] for i in cy],[i[0] for i in cy])
# export it in reverse order
df.iloc[::-1].T.to_dict(orient='rows')[0]
Returns:
{'a': ['a', 'b', 'a'], 'c': ['c', 'b', 'a', 'c'], 'd': ['d', 'b', 'a', 'd']}