def _degree_of_discrete_weighted(self, u, direction): if u is None: out = Counter() if direction == 'out': for u, v, ts, w in self.df.itertuples(weights=True): out[u] += w elif direction == 'in': for u, v, ts, w in self.df.itertuples(weights=True): out[v] += w elif direction == 'both': for u, v, ts, w in self.df.itertuples(weights=True): out[u] += w out[v] += w else: raise UnrecognizedDirection() return NodeCollection(Counter(out)) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() return df.w.sum()
def _duration_of_discrete(self, l=None, direction='out'): if not bool(self): if l is None: return LinkCollection() else: return .0 if l is None: # Count how many times a link appears if direction == 'out': def key(u, v): return (u, v) elif direction == 'in': def key(u, v): return (v, u) elif direction == 'both': # As we count both directions, so pairs can be sorted. def key(u, v): return tuple(sorted([u, v])) else: raise UnrecognizedDirection() return LinkCollection(Counter((key(a[0], a[1]) for a in iter(self)))) else: u, v = l if direction == 'out': df = self.df[(self.df.u == u) & (self.df.v == v)] elif direction == 'in': df = self.df[(self.df.v == u) & (self.df.u == v)] elif direction == 'both': df = self.df[self.df.u.isin({u, v}) & self.df.v.isin({u, v})] else: raise UnrecognizedDirection() return ITimeSetS(df.ts, discrete=True).size
def neighbors_of(self, u=None, direction='out'): if not bool(self): if u is None: return dict() else: return TemporalNodeSetDF() if u is None: neighbors = defaultdict(list) if direction == 'out': def add(key): neighbors[key[0]].append(key[1:]) elif direction == 'in': def add(key): neighbors[key[1]].append((key[0], ) + key[2:]) elif direction == 'both': def add(key): neighbors[key[0]].append(key[1:]) neighbors[key[1]].append((key[0], ) + key[2:]) else: raise UnrecognizedDirection() for key in itertuples_raw(self.df, discrete=self.discrete, weighted=False): add(key) return NodeCollection({ u: TemporalNodeSetDF( init_interval_df(data=ns, discrete=self.discrete, weighted=False, disjoint_intervals=False, keys=['u'])) for u, ns in iteritems(neighbors) }) else: if direction == 'out': df = self.df[self.df.u == u].drop( columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop( columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=False) else: raise UnrecognizedDirection() if self.weighted: df = df.drop(columns='w', merge=False) return TemporalNodeSetDF(df, disjoint_intervals=False)
def degree_of(self, u=None, direction='out', weights=False): if not bool(self): if u is None: return dict() else: return TemporalNodeSetDF() if u is None: degree = Counter() dc = (1 if self.discrete else 0) if direction == 'out': def add(u, v, ts, tf, w=1): degree[u] += (tf - ts + dc) * w elif direction == 'in': def add(u, v, ts, tf, w=1): degree[v] += (tf - ts + dc) * w elif direction == 'both': def add(u, v, ts, tf, w=1): degree[u] += (tf - ts + dc) * w degree[v] += (tf - ts + dc) * w else: raise UnrecognizedDirection() kargs = ({'weights': True} if self.weighted and weights else {}) for key in self.df.itertuples(**kargs): add(*key) return NodeCollection(degree) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u']).rename( columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v']) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u']).rename( columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v']), ignore_index=True) else: raise UnrecognizedDirection() if self.weighted and weights: return df.w.sum() else: df = (df.drop(columns=['w'], merge=False) if self.weighted else df) return TemporalNodeSetDF(df, disjoint_intervals=False, discrete=self.discrete).size
def times_of(self, l=None, direction='out'): if not bool(self): if l is None: return LinkCollection() else: return TimeSetDF() if l is None: times = defaultdict(list) di = False if direction == 'out': def add(key, time): times[key].append(time) elif direction == 'in': def add(key, time): times[key].append(time) elif direction == 'both': def add(key, time): times[tuple(sorted(key))].append(time) di = True else: raise UnrecognizedDirection() for key in self.df.itertuples(**({} if self.discrete else { 'bounds': True })): add(key[:2], key[2:]) return LinkCollection({ l: TimeSetDF( init_interval_df( data=ts, discrete=self.discrete, disjoint_intervals=not (di or self.weighted))) for l, ts in iteritems(times) }) else: mf, kw, = False, (['w'] if self.weighted else []) u, v = l if direction == 'out': df = self.df[(self.df.u == u) & (self.df.v == v)] elif direction == 'in': df = self.df[(self.df.v == u) & (self.df.u == v)] elif direction == 'both': df, mf = self.df[self.df.u.isin({u, v}) & self.df.v.isin({u, v})], True else: raise UnrecognizedDirection() return TimeSetDF(df.drop(columns=['u', 'v'] + kw, merge=(mf or self.weighted)), discrete=self.discrete)
def duration_of(self, l=None, weights=False, direction='out'): if not bool(self): if l is None: return LinkCollection() else: return .0 weighted = self.weighted and weights if l is None: times = defaultdict(float) dc = (1 if self.discrete else 0) if direction == 'out': def add(u, v, ts, tf, w=1): times[(u, v)] += (tf - ts + dc) * w elif direction == 'in': def add(u, v, ts, tf, w=1): times[(v, u)] += (tf - ts + dc) * w elif direction == 'both': def add(u, v, ts, tf, w=1): times[tuple(sorted([u, v]))] += (tf - ts + dc) * w else: raise UnrecognizedDirection() for args in itertuples_raw(self.df, discrete=True, weighted=weighted): add(*args) return LinkCollection({l: ts for l, ts in iteritems(times)}) else: di = False u, v = l if direction == 'out': df = self.df[(self.df.u == u) & (self.df.v == v)] elif direction == 'in': df = self.df[(self.df.v == u) & (self.df.u == v)] elif direction == 'both': df, di = self.df[self.df.u.isin({u, v}) & self.df.v.isin({u, v})], True else: raise UnrecognizedDirection() if weighted: return df.drop(columns=['u', 'v'], merge=di).measure_time(weights=True) else: return df.drop(columns=['u', 'v'] + self._wc, merge=di).measure_time()
def apply_direction_on_iter(iter_, direction='out'): if direction == 'in': iter_ = ((key[1], key[0]) + key[2:] for key in iter_) elif direction == 'both': iter_ = (it + key[2:] for key in iter_ for it in [(key[0], key[1]), (key[1], key[0])]) elif direction != 'out': raise UnrecognizedDirection() return iter_
def neighbors_at(self, u=None, t=None, direction='out'): if not bool(self): if u is None: return NodeCollection() if t is None: return TimeCollection() return NodeSetS() mf = (self.df_.merge_function if self.weighted else None) if u is None: if t is None: out = dict() for u, val in self._build_time_generator( set, set_unweighted_n_sparse, weighted=False, direction=direction, get_key=get_key_first, sparse=True): d = out.get(u, None) if d is None: out[u] = TimeSparseCollection([val], discrete=self.discrete, caster=NodeSetS) else: d.append(val) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t)[['u', 'v'] + self._wc], merge_function=mf, no_duplicates=False).neighbors_of( u=None, direction=direction) else: if direction == 'out': df = self.df[self.df.u == u].drop( columns=['u'] + self._wc, merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'] + self._wc, merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop( columns=['u'] + self._wc).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'] + self._wc, merge=True), ignore_index=True) else: raise UnrecognizedDirection() if t is None: return TemporalNodeSetDF(df).nodes_at(t=None) else: return NodeSetS(df[df.index_at(t)].u.values.flat)
def neighbors_of(self, u=None, direction='out'): if u is None: # A dictionary containing for its node it's set of neighbors neighbors = defaultdict(set) # Define a function for adding for its node it's neighbor. if direction == 'out': def add(u, v): neighbors[u].add(v) elif direction == 'in': def add(u, v): neighbors[v].add(u) elif direction == 'both': def add(u, v): neighbors[u].add(v) neighbors[v].add(u) else: raise UnrecognizedDirection() for key in iter(self): # Parse all elements. add(key[0], key[1]) # Return a node-collection of nodesets. return NodeCollection( {u: NodeSetS(s) for u, s in iteritems(neighbors)}) else: # In case we want only one element if direction == 'out': # Extract the series of elements. s = self.df[self.df.u == u].v elif direction == 'in': s = self.df[self.df.v == u].u elif direction == 'both': s = itertools.chain(self.df[self.df.u == u].v, self.df[self.df.v == u].u) else: raise UnrecognizedDirection() # Return a Nodeset. return NodeSetS(s)
def _degree_of_discrete(self, u, direction): if u is None: if direction == 'out': iter_ = (u for u, v, ts in self.df.itertuples()) elif direction == 'in': iter_ = (v for u, v, ts in self.df.itertuples()) elif direction == 'both': # Avoid double occurencies iter_ = (u for u, _, _ in set(p for a, b, c in self.df.itertuples() for p in [(a, b, c), (b, a, c)])) else: raise UnrecognizedDirection() return NodeCollection(Counter(iter_)) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() return ITemporalNodeSetDF(df, discrete=self.discrete).number_of_interactions
def temporal_neighborhood(self, ns, direction='out'): # if df join on u / combine (intersect) and the union intervals (for union) # if range derror = False if not isinstance(ns, ABC.TemporalNodeSet): raise UnrecognizedTemporalNodeSet('ns') assert self.discrete == ns.discrete cidf_ = class_interval_df(discrete=self.discrete, weighted=self.weighted) if isinstance(ns, TemporalNodeSetB): # if all nodes appear at all times # take the neighbors if direction == 'out': df = self.df.rename(columns={'v': 'u', 'u': 'v'}) df = df[df.v.isin(ns.nodeset_)].drop('v', axis=1) elif direction == 'in': df = self.df[self.df.v.isin(ns.nodeset_)].drop('v', axis=1) elif direction == 'both': df = self.df.rename(columns={'v': 'u', 'u': 'v'}) df = df[df.v.isin(ns.nodeset_)].drop('v', axis=1) df = df.append(self.df[self.df.v.isin(ns.nodeset_)].drop('v', axis=1)) else: derror = True if not derror: ts = ns.timeset_ if isinstance(ts, ABC.ITimeSet): ts = its_to_idf(ts) else: df, ts = cidf_(self.df), ts_to_df(ts) # and apply intersection for all keys with the same time-set df = df.intersection(df, ts, on_columns=['u', 'v'], by_key=False) else: if isinstance(ns, ABC.ITemporalNodeSet): df, base_df = self.df, ins_to_idf(ns) else: df, base_df = cidf_(self.df), tns_to_df(ns) if direction == 'out': df = df.map_intersection(base_df) elif direction == 'in': df = df.rename(columns={'u': 'v', 'v': 'u'}).map_intersection(base_df) elif direction == 'both': dfo, df = df, df.map_intersection(base_df) df = df.append(dfo.rename(columns={'u': 'v', 'v': 'u'}).map_intersection(base_df), ignore_index=True, merge=True) else: derror = True if derror: raise UnrecognizedDirection() if isinstance(df, cidf_): df = df.drop(columns=['tf']) return ITemporalNodeSetDF(df, no_duplicates=False, discrete=self.discrete)
def neighbors_of(self, u=None, direction='out'): if not bool(self): if u is None: return {} else: return ITemporalNodeSetDF() if u is None: neighbors = defaultdict(set) if direction == 'out': def add(u, v, ts): neighbors[u].add((v, ts)) elif direction == 'in': def add(u, v, ts): neighbors[v].add((u, ts)) elif direction == 'both': def add(u, v, ts): neighbors[u].add((v, ts)) neighbors[v].add((u, ts)) else: raise UnrecognizedDirection() for u, v, ts in self.df.itertuples(): # structure in neighboring relations for its node. add(u, v, ts) return NodeCollection({u: ITemporalNodeSetDF(ns) for u, ns in iteritems(neighbors)}) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() return ITemporalNodeSetDF(df, no_duplicates=False, discrete=self.discrete)
def temporal_neighborhood(self, tns, direction='out'): # if df join on u / combine (intersect) and the union intervals (for union) # if range derror = False if not isinstance(tns, ABC.TemporalNodeSet): raise UnrecognizedTemporalNodeSet('ns') if isinstance(tns, TemporalNodeSetB): if direction == 'out': df = self.df.rename(columns={'v': 'u', 'u': 'v'}) df = df[df.v.isin(tns.nodeset_)].drop('v', axis=1) elif direction == 'in': df = self.df[self.df.v.isin(tns.nodeset_)].drop('v', axis=1) elif direction == 'both': df = self.df.rename(columns={'v': 'u', 'u': 'v'}) df = df[df.v.isin(tns.nodeset_)].drop('v', axis=1, merge=False) df = df.append(self.df[self.df.v.isin(tns.nodeset_)].drop( 'v', axis=1, merge=False), merge=True) else: derror = True if not derror: df = df.intersection(ts_to_df(tns.timeset_), on_columns=['u', 'v'], by_key=False) else: base_df = tns_to_df(tns) if direction == 'out': df = self.df elif direction == 'in': df = self.df.rename(columns={'u': 'v', 'v': 'u'}) elif direction == 'both': df = self.df.append(self.df.rename(columns={ 'u': 'v', 'v': 'u' }), ignore_index=True, merge=True) else: derror = True df = df.map_intersection(base_df) if derror: raise UnrecognizedDirection() return TemporalNodeSetDF(df, disjoint_intervals=False, discrete=self.discrete)
def _degree_at_weighted(self, u, t, direction): if u is None: if t is None: out = dict() for u, val in self._build_time_generator( Counter, sum_counter_n, direction=direction, get_key=get_key_first): d = out.get(u, None) if d is None: out[u] = TimeCollection([val], discrete=self.discrete, instantaneous=False) else: d.append(val) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t)[['u', 'v', 'w']], weighted=True, merge_function=self.df_.merge_function, no_duplicates=False).degree( u=None, direction=direction, weights=True) else: if direction == 'out': df = self.df[self.df.u == u].drop( columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop( columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=True), ignore_index=True) else: raise UnrecognizedDirection() if t is None: return TimeCollection(self._build_time_generator( Counter, sum_counter_, direction=direction, df=df), discrete=self.discrete, instantaneous=False) else: return df.w[df.index_at(t)].sum()
def _degree_at_unweighted(self, u, t, direction): if u is None: if t is None: out = dict() for u, val in self._build_time_generator( set, len_set_n, direction=direction, get_key=get_key_first): d = out.get(u, None) if d is None: out[u] = TimeCollection([val], discrete=self.discrete, instantaneous=False) else: d.append(val) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t)[['u', 'v'] + self._wc], no_duplicates=False).degree( u=None, direction=direction) else: df = (self.df.drop(columns='w', merge=False) if self.weighted else self.df) if direction == 'out': df = df[df.u == u].drop( columns=['u'], merge=self.weighted).rename(columns={'v': 'u'}) elif direction == 'in': df = df[df.v == u].drop(columns=['v'], merge=self.weighted) elif direction == 'both': dfa = df[df.u == u].drop( columns=['u'], merge=False).rename(columns={'v': 'u'}) df = dfa.append(df[df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() if t is None: return TemporalNodeSetDF(df).n_at(t=None) else: return len(set(df.df_at(t).u.values.flat))
def get_maximal_cliques(df, direction='both'): S, S_set, R, times, nodes = deque(), set(), set(), dict(), dict() if direction == 'out': def as_link(u, v): return (u, v) def add_nodes(u, v): nodes[u].add(v) def add_element(times, l, ts, tf): times[l].append((ts, tf)) return True elif direction == 'in': def as_link(u, v): return (v, u) def add_nodes(u, v): nodes[v].add(u) def add_element(times, l, ts, tf): times[l].append((ts, tf)) return True elif direction == 'both': def as_link(u, v): return frozenset([u, v]) def add_nodes(u, v): nodes[v].add(u) nodes[u].add(v) def add_element(times, l, ts, tf): if len(times[l]): tsp, tfp = times[l][-1] assert ts >= tsp if ts <= tfp: times[l][-1] = (tsp, max(tf, tfp)) return False times[l].append((ts, tf)) return True else: raise UnrecognizedDirection() times, nodes = defaultdict(list), defaultdict(set) for u, v, ts, tf, in df[['u', 'v', 'ts', 'tf']].itertuples(index=False, name=None): # This a new instance add_nodes(u, v) if add_element(times, as_link(u, v), ts, tf): add_clique((frozenset([u, v]), (ts, ts), set()), S, S_set) while len(S) != 0: cnds, (ts, tf), can = S.pop() is_max = True # Grow time on the right side td = getTd(cnds, ts, tf, as_link, times) if td != tf: # nodes, (ts, tf), candidates add_clique((cnds, (ts, td), can), S, S_set) is_max = False # Grow node set can = set(can) if ts == tf: for u in cnds: neighbors = nodes[u] for n in neighbors: can.add(n) can -= cnds for node in can: if isClique(cnds, node, ts, tf, as_link, times): # Is clique! Xnew = set(cnds) | set([node]) add_clique((frozenset(Xnew), (ts, tf), can), S, S_set) is_max = False if is_max: R.add((cnds, (ts, tf))) return R
def _degree_at_unweighted(self, u=None, t=None, direction='out'): if not bool(self): if u is None: return NodeCollection() if t is None: return TimeCollection(discrete=self.discrete, instantaneous=True) return 0 if u is None: if t is None: out = dict() if direction == 'out': def add(d, u, v): d[u].add(v) elif direction == 'in': def add(d, u, v): d[v].add(u) elif direction == 'both': def add(d, u, v): d[u].add(v) d[v].add(u) else: raise UnrecognizedDirection() prev = None for u, v, ts in self.sort_df('ts').itertuples(): # Collect neighbors at each time-stamp if prev is None: cache = defaultdict(set) prev = ts elif ts != prev: for z, s in iteritems(cache): if z in out: # and calculate their size out[z].it.append((prev, len(s))) else: # in a TimeCollection of ascending time for each node out[z] = TimeCollection([(prev, len(s))], discrete=self.discrete, instantaneous=True) cache = defaultdict(set) prev = ts add(cache, u, v) # Add the remaining, from the cache for u, s in iteritems(cache): if u in out: out[u].it.append((prev, len(s))) else: out[u] = TimeCollection([(prev, len(s))], discrete=self.discrete, instantaneous=True) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t).drop(columns=['ts']), weighted=self.weighted).degree(u=None, direction=direction) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() if t is None: dt = defaultdict(set) # Collect all nodes for each time-stamp for u, ts in df.itertuples(): dt[ts].add(u) return TimeCollection(sorted(list((ts, len(us)) for ts, us in iteritems(dt))), discrete=self.discrete, instantaneous=True) else: return len(set(df.df_at(t).u.values.flat))
def neighbors_at(self, u=None, t=None, direction='out'): if not bool(self): if u is None: return NodeCollection() if t is None: return TimeCollection(discrete=self.discrete, instantaneous=True) return NodeSetS() if u is None: if t is None: out = dict() if direction == 'out': def add(d, u, v): d[u].add(v) elif direction == 'in': def add(d, u, v): d[v].add(u) elif direction == 'both': def add(d, u, v): d[u].add(v) d[v].add(u) else: raise UnrecognizedDirection() prev = None for u, v, ts in self.sort_df('ts').itertuples(): # Iterate in ascending time and at each instant collect for each node the set of its neighbors if prev is None: prev, cache = ts, defaultdict(set) elif ts != prev: # For each node for z, s in iteritems(cache): if z in out: # Or append it if it exists out[z].it.append((prev, NodeSetS(s))) else: # Initialize a time-collection with the time-stamp and the node-set out[z] = TimeCollection([(prev, NodeSetS(s))], instantaneous=True, discrete=self.discrete) prev, cache = ts, defaultdict(set) add(cache, u, v) # Add also remaining elements. for u, s in iteritems(cache): if u in out: out[u].it.append((prev, NodeSetS(s))) else: out[u] = TimeCollection([(prev, NodeSetS(s))], instantaneous=True, discrete=self.discrete) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t).drop(columns=['ts']), weighted=self.weighted).neighbors_of(u=None, direction=direction) else: di = True if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u']).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v']) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u']).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v']), ignore_index=True) di = False else: raise UnrecognizedDirection() if t is None: return ITemporalNodeSetDF(df[['u', 'ts']], no_duplicates=di, discrete=self.discrete).nodes_at(t=None) else: return NodeSetS(df.df_at(t).u.values.flat)
def _degree_at_weighted(self, u, t, direction): if u is None: if t is None: out = dict() if direction == 'out': def add(d, u, v, w): d[u] += w elif direction == 'in': def add(d, u, v, w): d[v] += w elif direction == 'both': def add(d, u, v, w): d[u] += w d[v] += w else: raise UnrecognizedDirection() prev = None for u, v, ts, w in self.sort_df('ts').itertuples(weights=True): # Iterate in ascending time if prev is None: # For each node add all the weights for all its neighbors cache = Counter() prev = ts elif ts != prev: for z, weight in iteritems(cache): if z in out: # Append in ascending time inside the TimeCollection out[z].it.append((prev, weight)) else: # Initialize inside the TimeCollection out[z] = TimeCollection([(prev, weight)], discrete=self.discrete, instantaneous=True) cache = Counter() prev = ts add(cache, u, v, w) # Remove the remaining. for u, weight in iteritems(cache): if u in out: out[u].it.append((prev, weight)) else: out[u] = TimeCollection([(prev, weight)], discrete=self.discrete, instantaneous=True) return NodeCollection(out) else: return LinkSetDF(self.df.df_at(t).drop(columns=['ts']), weighted=self.weighted, merge_function=self.df_.merge_function).degree(u=None, direction=direction, weights=True) else: if direction == 'out': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) elif direction == 'in': df = self.df[self.df.v == u].drop(columns=['v'], merge=False) elif direction == 'both': df = self.df[self.df.u == u].drop(columns=['u'], merge=False).rename(columns={'v': 'u'}) df = df.append(self.df[self.df.v == u].drop(columns=['v'], merge=False), ignore_index=True, merge=True) else: raise UnrecognizedDirection() if t is None: dt = Counter() for u, ts, w in df.itertuples(weights=True): # collect all the weights for its time-stamp. dt[ts] += w return TimeCollection(sorted(list(iteritems(dt))), discrete=self.discrete, instantaneous=True) else: return df.df_at(t).w.sum()