forked from hekimgil/imdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
model0a.py
184 lines (168 loc) · 6.96 KB
/
model0a.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# -*- coding: utf-8 -*-
"""
Python code to read .tsv İMDB data and store it in a sqlite database
This model assumes movies as nodes and common actors/actresses as weighted
edges. Different 20-year periods are used to set up separate networks and basic
data such as number of nodes, number of edges, and distribution of sizes
of connected components are examined to get a general idea on various 20-year
windows.
THIS VERSION PROCESSES THE WHOLE MOVIE DATABASE INSTEAD OF 20-YEAR WINDOWS.
@author: Hakan Hekimgil
"""
import numpy as np
import pandas as pd
import sqlite3
import networkx as nx
# initialize graph
G = nx.Graph()
# connect to database
conn = sqlite3.connect("data/imdblite.db")
db = conn.cursor()
# start reading and moving to db
# transfer titles
print("Reading titles...")
numtitles = 0
titleset = set()
peopleset = set()
# some helper functions
def titleinfo(n):
conntemp = sqlite3.connect("data/imdblite.db")
dbtemp = conntemp.cursor()
dbtemp.execute("SELECT * FROM titles WHERE tconst = ?;", (int(n),))
infotemp = dbtemp.fetchone()
conntemp.close()
return infotemp
def findtitle(txt):
conntemp = sqlite3.connect("data/imdblite.db")
dbtemp = conntemp.cursor()
dbtemp.execute("SELECT * FROM titles WHERE primaryTitle = ?;", (txt,))
infotemp = dbtemp.fetchone()
conntemp.close()
return infotemp
def peopleinfo(n):
conntemp = sqlite3.connect("data/imdblite.db")
dbtemp = conntemp.cursor()
dbtemp.execute("SELECT * FROM people WHERE nconst = ?;", (int(n),))
infotemp = dbtemp.fetchone()
conntemp.close()
return infotemp
def findperson(txt):
conntemp = sqlite3.connect("data/imdblite.db")
dbtemp = conntemp.cursor()
dbtemp.execute("SELECT * FROM people WHERE primaryName = ?;", (txt,))
infotemp = dbtemp.fetchone()
conntemp.close()
return infotemp
infodf = pd.DataFrame(columns=["period", "# vertices", "# edges", "density", "max degree", "largest CC"])
ccdist = []
top50df = pd.DataFrame(columns=["degree", "name", "startYear"])
# read and add actors/actresses
db.execute("SELECT id FROM categories WHERE category = ? OR category = ?;", ("actor","actress"))
catids = db.fetchall()
assert len(catids) == 2
for year1 in range(1980,2010,100):
year2 = year1 + 99
G.clear()
# read and add titles
# db.execute("SELECT * FROM titles WHERE startYear >= ? AND startYear <= ?;", (year1, year2))
# movies = pd.DataFrame(db.fetchall(), columns=["tconst", "primaryTitle", "startYear", "endYear", "runtimeMinutes", "genre1", "genre2","genre3"])
# rows, columns = movies.shape
# print("{:,} titles found...".format(rows))
# for row in movies.itertuples(index=False):
# titleid = row.tconst
# titlename = row.primaryTitle
# #print(titleid, titlename)
# titleset.add(titleid)
# G.add_node(titleid, title=titlename)
# numtitles += 1
# print("{:,} titles added as nodes...".format(numtitles))
db.execute(
"SELECT DISTINCT t.tconst, nconst " +
"FROM (SELECT tconst FROM titles WHERE startYear >= ? AND startYear <= ?) AS t " +
"INNER JOIN (SELECT nconst, tconst FROM principals WHERE catid = ? OR catid = ?) AS p " +
"ON t.tconst = p.tconst " +
"ORDER BY nconst;", (year1, year2, catids[0][0], catids[1][0]))
edgeinfo = pd.DataFrame(db.fetchall(), columns=["tconst", "nconst"])
titleset = set(edgeinfo.tconst.unique())
print("{:,} nodes determined...".format(len(titleset)))
G.add_nodes_from(edgeinfo.tconst.unique())
print("{:,} nodes added to graph...".format(G.number_of_nodes()))
prevedge = None
tempset = set()
temp = 0
for row in edgeinfo.itertuples(index=False):
temp += 1
if temp % 250000 == 0:
print("checking row {:,}".format(temp))
titleid = row.tconst
actid = row.nconst
#print(titleid, actid)
if actid != prevedge:
prevedge = actid
del(tempset)
tempset = set([titleid])
else:
for node in tempset:
if G.has_edge(node, titleid):
G[node][titleid]["weight"] += 1
else:
G.add_edge(node, titleid, weight=1)
tempset.add(titleid)
del(edgeinfo)
# rows, columns = movies.shape
#print("Number of nodes: ", G.number_of_nodes())
#print("Number of edges: ", G.number_of_edges())
print(nx.info(G))
if G.number_of_nodes() <= 20:
print("Nodes: ", G.nodes())
for node in G.nodes():
print(G.node[node])
if G.number_of_edges() <= 20:
print("Edges: ", G.edges())
print("Network density:", nx.density(G))
maxd = max([d for n,d in G.degree()])
d50th = sorted([d for n,d in G.degree()])[-50]
print("Maximum degree:", maxd)
top50dmov = sorted([(d,n) for n,d in G.degree() if d >= d50th], reverse=True)
top50dmovfull = [(d,titleinfo(n)) for d,n in top50dmov]
ind=0
for t in top50dmovfull:
ind += 1
year = np.NAN
if t[1][2] != "NULL":
year = int(t[1][2])
top50dfrow = pd.Series({"degree":int(t[0]),
"name":t[1][1],
"startYear":year}, name=ind)
top50df = top50df.append(top50dfrow)
#print("Movies with maximum degree:", [titleinfo(m) for m in top20dmov])
connecteds = list(nx.connected_components(G))
maxconnectedsize = max([len(c) for c in connecteds])
#connecteds = nx.connected_components(G)
#largestconnected = max(connecteds, key=len)
#maxconnectedsize = len(largestconnected)
#diameter = nx.diameter(G.subgraph(largestconnected))
print("Size of largest connected component:", maxconnectedsize)
#print("Diameter of largest connected component:", diameter)
infodfrow = pd.Series({"period":str(year1)+"-"+str(year2),
"# vertices":G.number_of_nodes(),
"# edges":G.number_of_edges(),
"density":nx.density(G),
"max degree":max([d for n,d in G.degree()]),
"largest CC":maxconnectedsize},
name=str(year1)+"-"+str(year2))
infodf = infodf.append(infodfrow)
temp = set([len(c) for c in connecteds])
temp2 = [len(c) for c in connecteds]
connectedsizes = {k:temp2.count(k) for k in temp}
ccdist.append((str(year1)+"-"+str(year2),connectedsizes))
print("Number of connected components according to size:", connectedsizes)
#G.clear()
conn.close()
print("\n\nMovies as vertices and actors/actresses as weighted (by number) edges:")
print("----------------------------------------------------------------------")
print(infodf)
print("\n\nMovies with maximum degrees:")
print("----------------------------")
print(top50df)
#print(ccdist)