2017-02-01 10 views
0

Я пытаюсь получить количество сетевых кромок из нормализованной базы данных SQLite, которая была нормирована следующим образом:Получить сетевые кромки из таблиц SQL для NetworkX в питоне

Authors     Paper      Paper_Authors 
| authorID | name | etc | paperID | title | etc | paperID | authorID | 
| 1  | .... | ... | 1 | ..... | ... | 1  | 1  | 
| 2  | .... | ... | 2 | ..... | ... | 1  | 2  | 
| 3  | .... | ... | . | ..... | ... | 1  | 3  | 
| 4  | .... | ... | 60,000 | ..... | ... | 2  | 1  | 
| 5  | .... | ...        | 2  | 4  | 
| .  | .... | ...        | 2  | 5  | 
| 120,000 | .... | ...        | .  | .  | 
                 | 60,000 | 120,000 | 

С где-то в районе 120,000 авторов и 60 000 документов, а индексная таблица насчитывает около 250 000 строк.

Я пытаюсь получить это в NetworkX сделать некоторый анализ связности, вводя узлы прост:

conn = sqlite3.connect('../input/database.sqlite') 
c = conn.cursor() 
g = nx.Graph() 
c.execute('SELECT authorID FROM Authors;') 
authors = c.fetchall() 
g.add_nodes_from(authors) 

Проблема, которую я имею возникает от попыток определить края скормить NetworkX, что требует значения в кортеже двух узлов для соединения, используя приведенные выше данные в качестве примера;

[(1,1),(1,2),(1,3),(2,3),(1,4),(1,5),(4,5)] 

Опишет набор данных выше.

У меня есть следующий код, который работает, но некрасиво:

def coauthors(pID): 
    c.execute('SELECT authorID \ 
       FROM Paper_Authors \ 
       WHERE paperID IS ?;', (pID,)) 
    out = c.fetchall() 
    g.add_edges_from(itertools.product(out, out)) 

c.execute('SELECT COUNT() FROM Papers;') 
papers = c.fetchall() 

for i in range(1, papers[0][0]+1): 
    if i % 1000 == 0: 
     print('On record:', str(i)) 
    coauthors(i) 

Это работает цикл по каждому из документов в базе данных, возвращая список авторов и итеративно делает список автор комбинационных кортежей и добавление их к сети в поэлементном способе, который работает, но потребовалось 30 - 45 минут:

print(nx.info(g)) 
Name: 
Type: Graph 
Number of nodes: 120670 
Number of edges: 697389 
Average degree: 11.5586 

Так что мой вопрос, есть более элегантный способ прийти к такому же результату, в идеале с paperID как метка края, чтобы упростить навигацию сеть за пределами networkX.

+0

Не определяется ли сеть непосредственно строками в 'Paper_Authors'? Как отображается список кортежей, связанный с данными примера? –

+0

@CL. к сожалению, нет, поскольку networkx, похоже, требует кортеж, который определяет край, который должен быть в формате 'edge = (node, node)', поэтому в этом случае 'paper = (автор, автор)', используя данные 'Paper_Authors', быть в формате 'edge = (author, paper)', если не существует способа определить 2 типа узлов, а затем как-то свернуть сеть. –

+0

@CL. Расследовал это немного больше, и он действительно работает, если я даю авторам и документам другой префикс и по существу имеет два разных типа узлов: один для бумаг и один для авторов. –

ответ

2

Вы можете получить все комбинации авторов для каждой бумаги с автообъединением:

SELECT paperID, 
     a1.authorID AS author1, 
     a2.authorID AS author2 
FROM Paper_Authors AS a1 
JOIN Paper_Authors AS a2 USING (paperID) 
WHERE a1.authorID < a2.authorID;   -- prevent duplicate edges 

Это будет ужасно неэффективно, если у вас есть индекс по paperID, или лучше, covering index на обоих paperID и authorID, или лучше, WITHOUT ROWID table.

+0

Большое спасибо, это отлично работало и заняло около 2 секунд около 600 000 строк вывода, я также посмотрю на другие ускорения. Большое спасибо за ответ, проблема, с которой я столкнулась, была в том, как я могу выбрать authorID, когда я уже выбираю authorID. –