Ошибка при создании графика и выполнении предсказания ссылок с использованием networkx в python - PullRequest
0 голосов
/ 03 мая 2019

Я пытаюсь построить график, используя CSV-файл, который содержит информацию о ребрах, профессии и возрасте узлов. Я назначаю сообщества каждому узлу и выполняю прогнозирование канала.

import networkx as nx
import csv
engineers1 = []
engineers2 = []
engineers3 = []
engineers4 = []
engineers5 = []
actors1= []
actors2= []
actors3= []
actors4= []
actors5= []
writers1 = []
writers2= []
writers3= []
writers4 = []
writers5 = []
doctors1= []
doctors2= []
doctors3= []
doctors4= []
doctors5= []
drivers1=[]
drivers2=[]
drivers3=[]
drivers4=[]
drivers5=[]
teachers1=[]
teachers2=[]
teachers3=[]
teachers4=[]
teachers5=[]
nodes=[]
g=nx.Graph()

for i in range(0,4038):
    g.add_node(i)

with open("asd1.csv",'r') as csv_file:
    csv_reader=csv.DictReader(csv_file)

    for line in csv_reader:
        g.add_edge(line['first'],line['second'])

csv_file.close()

with open("asd1.csv",'r') as csv_file:
    csv_reader=csv.DictReader(csv_file)
    for line in csv_reader:
         if (line['profession'] == 'actor' and line['age'] >= '13' and 
line['age'] <= '17'):
            actors1.append(line['name'])
        if (line['profession'] == 'actor' and line['age'] >= '18' and 
line['age'] <= '29'):
          actors2.append(line['name'])
        if (line['profession'] == 'actor' and line['age'] >= '30' and 
line['age'] <= '49'):
        actors3.append(line['name'])
    if (line['profession'] == 'actor' and line['age'] >= '50' and line['age'] <= '64'):
        actors4.append(line['name'])
    if (line['profession'] == 'actor' and line['age'] >= '65'):
        actors5.append(line['name'])

    if (line['profession'] == 'eng' and line['age'] >= '13' and line['age'] <= '17'):
        engineers1.append(line['name'])
    if (line['profession'] == 'eng' and line['age'] >= '18' and line['age'] <= '29'):
        engineers2.append(line['name'])
    if (line['profession'] == 'eng' and line['age'] >= '30' and line['age'] <= '49'):
        engineers3.append(line['name'])
    if (line['profession'] == 'eng' and line['age'] >= '50' and line['age'] <= '64'):
        engineers4.append(line['name'])
    if (line['profession'] == 'eng' and line['age'] >= '65'):
        engineers5.append(line['name'])

    if (line['profession'] == 'teacher' and line['age'] >= '13' and line['age'] <= '17'):
        teachers1.append(line['name'])
    if (line['profession'] == 'teacher' and line['age'] >= '18' and line['age'] <= '29'):
        teachers2.append(line['name'])
    if (line['profession'] == 'teacher' and line['age'] >= '30' and line['age'] <= '49'):
        teachers3.append(line['name'])
    if (line['profession'] == 'teacher' and line['age'] >= '50' and line['age'] <= '64'):
        teachers4.append(line['name'])
    if (line['profession'] == 'teacher' and line['age'] >= '65'):
        teachers5.append(line['name'])

    if (line['profession'] == 'driver' and line['age'] >= '13' and line['age'] <= '17'):
        drivers1.append(line['name'])
    if (line['profession'] == 'driver' and line['age'] >= '18' and line['age'] <= '29'):
        drivers2.append(line['name'])
    if (line['profession'] == 'driver' and line['age'] >= '30' and line['age'] <= '49'):
        drivers3.append(line['name'])
    if (line['profession'] == 'driver' and line['age'] >= '50' and line['age'] <= '64'):
        doctors4.append(line['name'])
    if (line['profession'] == 'driver' and line['age'] >= '65'):
        drivers5.append(line['name'])

    if (line['profession'] == 'doctor' and line['age'] >= '13' and line['age'] <= '17'):
        doctors1.append(line['name'])
    if (line['profession'] == 'doctor' and line['age'] >= '18' and line['age'] <= '29'):
        doctors2.append(line['name'])
    if (line['profession'] == 'doctor' and line['age'] >= '30' and line['age'] <= '49'):
        doctors3.append(line['name'])
    if (line['profession'] == 'doctor' and line['age'] >= '50' and line['age'] <= '64'):
        drivers4.append(line['name'])
    if (line['profession'] == 'doctor' and line['age'] >= '65'):
        doctors5.append(line['name'])

csv_file.close()

print("actors having age between 13 and 17: ",actors1) 
print("actors having age between 18 and 29: ",actors2)
print("actors having age between 30 and 49: ",actors3) 
print("actors having age between 50 and 64: ",actors4)
print("actors having age 65 and above: ",actors5)
print('\n')

print("engineers having age between 13 and 17: ",engineers1)
print("engineers having age between 18 and 29: ",engineers2)
print("engineers having age between 30 and 49: ",engineers3)
print("engineers having age between 50 and 64: ",engineers4)
print("engineers having age 65 and above: ",engineers5)
print('\n')

print("teachers having age between 13 and 17: ",teachers1)
print("teachers having age between 18 and 29: ",teachers2)
print("teachers having age between 30 and 49: ",teachers3)
print("teachers having age between 50 and 64: ",teachers4)
print("teachers having age 65 and above: ",teachers5)
print('\n')

print("drivers having age between 13 and 17: ",drivers1)
print("drivers having age between 18 and 29: ",drivers2)
print("drivers having age between 30 and 49: ",drivers3)
print("drivers having age between 50 and 64: ",drivers4)
print("drivers having age 65 and above: ",drivers5)
print('\n')

print("doctors having age between 13 and 17: ",doctors1)
print("doctors having age between 18 and 29: ",doctors2)
print("doctors having age between 30 and 49: ",doctors3)
print("doctors having age between 50 and 64: ",doctors4)
print("doctors having age 65 and above: ",doctors5)
print('\n')

for i in range(0,4038):
    g.node[i]['community']=0

for x1 in actors1:
    g.node[x1]['community']=0
for x2 in actors2:
    g.node[x2]['community']=1 
for x3 in actors3:
    g.node[x3]['community']=2
for x4 in actors4:
    g.node[x4]['community']=3
for x5 in actors5:
    g.node[x5]['community']=4
for x6 in engineers1:
    g.node[x6]['community']=5
for x7 in engineers2:
    g.node[x7]['community']=6
for x8 in engineers3:
    g.node[x8]['community']=7
for x9 in engineers4:
    g.node[x9]['community']=8
for x10 in engineers5:
    g.node[x10]['community']=9
for x11 in teachers1:
    g.node[x11]['community']=10
for x12 in teachers2:
    g.node[x12]['community']=11
for x13 in teachers3:
    g.node[x13]['community']=12
for x14 in teachers4:
    g.node[x14]['community']=13
for x15 in teachers5:
    g.node[x15]['community']=14
for x16 in drivers1:
    g.node[x16]['community']=15
for x17 in drivers2:
    g.node[x17]['community']=16
for x18 in drivers3:
    g.node[x18]['community']=17
for x19 in drivers4:
    g.node[x19]['community']=18
for x20 in drivers5:
    g.node[x20]['community']=19
for x21 in doctors1:
    g.node[x21]['community']=20
for x22 in doctors2:
   g.node[x22]['community']=21
for x23 in doctors3:
    g.node[x23]['community']=22
for x24 in doctors4:
    g.node[x24]['community']=23
for x25 in doctors5:
    g.node[x25]['community']=24

print(g.nodes())
l=list(nx.cn_soundarajan_hopcroft(g))
print(l)

1 Ответ

0 голосов
/ 06 мая 2019

Пролог

Я очень рекомендую вам прочитать ЛЮБУЮ хорошую книгу по программированию, которая объясняет алгоритмы. Ваша проблема может быть решена буквально несколькими строками кода.

Акт 1

Посмотри на свою проблему. У вас есть несколько профессий, несколько возрастных групп и имена в качестве уникальных идентификаторов. И вы хотите отличать их друг от друга. Теперь посмотрите на ваш код. Для решения вашей проблемы вы создаете уникальный список для каждой комбинации возраста и профессии. Это наименее модифицируемая структура, которую можно создать. Если вам придется добавить еще пять профессий (есть тысячи различных профессий), вам придется буквально удвоить свой код. Более того, вы можете легко сделать ошибку при копировании. Обычный merchandiser3 вместо merchandiser4 может превратить ваши следующие два часа в ад от красных глаз. Смотри, у тебя уже есть ошибка внутри твоего кода!

if (line['profession'] == 'doctor' and line['age'] >= '13' and line['age'] <= '17'):
    doctors1.append(line['name'])
if (line['profession'] == 'doctor' and line['age'] >= '18' and line['age'] <= '29'):
    doctors2.append(line['name'])
if (line['profession'] == 'doctor' and line['age'] >= '30' and line['age'] <= '49'):
    doctors3.append(line['name'])
if (line['profession'] == 'doctor' and line['age'] >= '50' and line['age'] <= '64'):
    # Hello, guys! I am ready to torture his brain and eyes for hours!!
    drivers4.append(line['name'])
if (line['profession'] == 'doctor' and line['age'] >= '65'):
    doctors5.append(line['name'])

И, как последний выстрел в голову, вам не нужны все эти списки. Вы можете создать, например, дикт для каждой профессии. Или что-то другое. Но вы можете заметить, что ваши данные имеют очень-очень повторяющуюся структуру для каждого человека. Имя, возраст, профессия ... Подождите, где мы взяли данные? CSV файл? И что такое файл CSV?

Да.

Таблица.

Акт 2

Если вы читаете данные из таблицы, рекомендуется сохранить эти данные в таблице! (Ну, большую часть времени ...) В Python есть замечательная библиотека для таблиц - Pandas. Все ваши сотни строк могут быть сокращены до одной-двух десятков! Теперь внимательно посмотри на мои руки, магия начинается ...

Ноль. Мы импортируем панд:

import pandas as pd

Во-первых. Мы создаем отдельную функцию для возрастной кластеризации. Если наш Большой Босс скажет нам, чтобы мы справились с 11-летними нейробиологами, мы будем в полной готовности:

def get_age_cluster(age):
    a = int(age)
    if a >= 0 and a <= 12:
        return '<13'
    if a >= 13 and a <= 17:
        return '13-17'
    if a >= 18 and a <= 29:
        return '18-29'
    if a >= 30 and a <= 49:
        return '30-49'
    if a >= 50 and a <= 64:
        return '50-64'
    elif a >= 65:
        return '>64'

Во-вторых. Мы читаем CSV. Вы делаете это вручную, строка за строкой, обрабатывая каждую возможную комбинацию ... Почему ?! Это обычная операция! Люди уже написали это давным-давно! Будьте ленивы!

(Это совет моего старого сенсея, который я храню в своем сердце годами! Шутка. У меня нет сердца.)

df=pd.read_csv('TF.csv')

Да, это все. Да. В самом деле. Одна линия. Двадцать четыре символа (запомните это число !!). Теперь давайте подружимся с нашими десятью маленькими милашками:

==============================

Мы только что загрузили CSV, но не преобразовали столбец age. Он содержит возрасты, но должен содержать кластеры. Не проблема!

df['age'] = df['age'].apply(get_age_cluster)

Готово! Вы можете применять любые функции преобразования к строкам или столбцам таблицы. Таким образом, нам не нужно сортировать возрасты, сортировать возрасты и возрасты, сортировать возрасты и ... Мы можем просто написать красивую строчку. Вот результат:

===============================

Вы можете заметить, что у нас есть несколько столбцов мусора. Не проблема!

df = df.drop('waka', axis=1) df = df.drop('we_dont_need_this_column', axis=1)

И у нас есть маленький красивый столик:

=======================

Теперь к основному заданию. Получить все имена в соответствии с каждой профессией и возрастом. Панды имеют много-много функций с группировкой. Давайте использовать самое простое:

grouped = df.groupby(['profession', 'age'])
for group in grouped.groups:
    print(group, list(grouped.get_group(group)['name']))

Мы получаем сгруппированную структуру с возрастными группами профессий: grouped = df.groupby(['profession', 'age']), и для каждой группы в этой структуре: for group in grouped.groups: мы печатаем: print() список столбцов 'name' в каждой группе: grouped.get_group(group)['name']) , И вот результат:

('eng', '30-49') ['Cthulhu']
('driver', '18-29') ['John Doe 3']
('actor', '13-17') ['John Doe 4']
('actor', '18-29') ['Yog-Sothoth']
('teacher', '18-29') ['John Doe 2', 'Shub-Niggurath']
('eng', '>64') ['Fblthp the Lost']
('driver', '<13') ['Azathoth']
('doctor', '18-29') ['Nyarlathotep']
('doctor', '30-49') ['John Doe 1']

А вот и весь код:

import pandas as pd

def get_age_cluster(age):
    a = int(age)
    if a >= 0 and a <= 12:
        return '<13'
    if a >= 13 and a <= 17:
        return '13-17'
    if a >= 18 and a <= 29:
        return '18-29'
    if a >= 30 and a <= 49:
        return '30-49'
    if a >= 50 and a <= 64:
        return '50-64'
    elif a >= 65:
        return '>64'

df=pd.read_csv('TF.csv')
df['age'] = df['age'].apply(get_age_cluster)
df = df.drop('waka', axis=1)
df = df.drop('we_dont_need_this_column', axis=1)
grouped = df.groupby(['profession', 'age'])
for group in grouped.groups:
    print(group, list(grouped.get_group(group)['name']))

Двадцать четыре строки. Я думаю, что теперь мы можем называть себя Фантастической Двадцатью Четверкой. Это как Фантастическая четверка, но Фантастическая двадцать четвертая. Но у нас все еще есть наш Graph Doom ...

Акт 3

Мы создали таблицу, сделали некоторые преобразования, отсортировали и отфильтровали ее. Но у вас есть другая проблема - График. И эта проблема сложнее, чем первая.

Вы читаете узлы (люди) и ребра (я не знаю, что именно. Отношения?) Из одного файла.Это заставляет ваш граф иметь сильное ограничение - количество узлов равно количеству ребер.Это очень редкий случай.Я думаю, что вы сделали что-то не так прямо перед тем, как начали писать этот сценарий.Я рекомендую вам иметь разные файлы (или, по крайней мере, разные секции в одном файле) для узлов и ребер.Но!Давайте предположим, что вы делаете именно то, что хотите, и у каждого человека (и, конечно, Ктулху!) Есть только одно преимущество.В этом случае мы можем построить наш граф только с двумя строками кода:

G = nx.Graph()
G.add_edges_from(df[['first', 'second']].values)

Бинго!Мы сделали.Теперь давайте возьмем эту странную сложную вещь:

Установите сообщество каждого узла (ЗАМЕЧАНИЕ, ЧТО ВАМ НУЖНО ДЛЯ АЛГОРИТМА):

for n in G.nodes:
    G.nodes[n]['community'] = 0

И вычислите ЭТО:

csh = nx.cn_soundarajan_hopcroft(G)

И мы получаем итератор.Преобразуйте его в список и получите результат:

[(1, 8, 2),
 (1, 9, 0),
 (1, 2, 4),
 (1, 4, 0),
 (1, 6, 2),
 (2, 8, 2),
 (2, 9, 2),
 (2, 5, 0),
 (2, 6, 2),
 (3, 9, 0),
 (3, 4, 2),
 (3, 5, 2),
 (3, 6, 0),
 (3, 7, 4),
 (4, 8, 0),
 (4, 5, 2),
 (4, 7, 2),
 (5, 8, 0),
 (5, 9, 0),
 (5, 7, 2),
 (6, 8, 0),
 (6, 9, 2),
 (6, 7, 0),
 (7, 8, 0),
 (7, 9, 0),
 (8, 9, 0)]

Grand Finale

Надеюсь, вам понравилась моя маленькая музыкальная пьеса, которую я для вас написал :) I рекомендую написать хорошую книгу по программированию на Python и книгу по алгоритмам.Удачи!

...