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 duration_of(self, l=None, direction='out', weights=False): """Returns the total duration of a link. Parameters ---------- l : (Node_Id, Node_Id) or None direction : string={'in', 'out', 'both'}, default='both' Returns ------- time : Real or dict Returns the the total time that link(s) (u, v)[direction='out'], (v, u)[direction='in'] or 'both' (u, v) and (v, u) appear. If l is None returns a dictionary of all links with their times. """ if self.discrete: return self._duration_of_discrete(l=l, direction=direction) else: if l is None: from stream_graph.collections import LinkCollection if self.weighted: return LinkCollection({l[:2]: 0. for l in self.linkset}) else: return LinkCollection({l: 0. for l in self.linkset}) else: return .0
def common_time_pair(self, l=None): if l is None or self._common_time_pair__list_input(l): if not bool(self): return LinkCollection(dict()) df = self.df.events active_nodes = set() e = df.t.iloc[0] if l is None: common_times = Counter() def add_item(active_nodes, ct): for u, v in combinations(active_nodes, 2): common_times[(u, v)] += ct else: links = set(l) common_times = {l: 0 for l in links} allowed_nodes = set(c for a, b in links for c in [a, b]) def add_item(active_nodes, ct): active_set = active_nodes & allowed_nodes if len(common_times) <= (len(active_set) * (len(active_set) - 1)) / 2: for (u, v) in common_times.keys(): if u in active_set and v in active_set: common_times[(u, v)] += ct else: for u, v in combinations(active_set, 2): if (u, v) in common_times: common_times[(u, v)] += ct if (v, u) in common_times: common_times[(v, u)] += ct dc = (1 if self.discrete else 0) for u, t, f in df.itertuples(index=False, name=None): ct = (len(active_nodes) - 1) * (t - e + dc) if ct > .0: add_item(active_nodes, ct) if f: # start active_nodes.add(u) else: # finish active_nodes.remove(u) e = t return LinkCollection(common_times) else: u, v = l if bool(self): idxa, idxb = (self.df.u == u), (self.df.u == v) if idxa.any() and idxb.any(): return self.df[idxa].intersection_size(self.df[idxb]) return 0.
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 times_of(self, l=None, direction='out'): if not bool(self): if l is None: return {} else: return TimeSetDF() if l is None: if direction == 'out': def key(u, v): return (u, v) elif direction == 'in': def key(u, v): return (v, u) elif direction == 'both': def key(u, v): return tuple(sorted([u, v])) else: raise UnrecognizedDirection() times = defaultdict(set) for u, v, ts in self.df.itertuples(index=False, name=None): # collect the time-stamps for its pair times[key(u, v)].add(ts) return LinkCollection({l: ITimeSetS(ts, discrete=self.discrete) for l, ts in iteritems(times)}) 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'].values.flat, discrete=self.discrete)
def common_time_pair(self, l=None): if l is None: return LinkCollection({(u, v): self.total_time for u, v in combinations(self.nodeset_, 2)}) elif isinstance(l, Iterable) and not (isinstance( l, tuple) and len(l) == 2 and any(not isinstance(a, Iterable) for a in l)): nodes, links = set(self.nodeset_) & set(a for u, v in l for a in (u, v)), set(l) return LinkCollection({(u, v): self.total_time for u, v in permutations(nodes, 2) if (u, v) in links}) if bool(self) and l[0] in self.nodeset_ and l[1] in self.nodeset_: return self.total_time return 0.
def _duration_of_unweighted(self, l, direction): if l is None: from stream_graph.collections import LinkCollection times = self.times_of(None, direction=direction) return LinkCollection({l: t.size for l, t in times}) else: return self.times_of(l=l, direction=direction).size
def _common_time_pair_discrete(self, l=None): if l is None or self._common_time_pair__list_input(l): carrier = defaultdict(set) # For each node take the set of time-stamps. for u, ts in iter(self): carrier[u].add(ts) # Take all the valid pairs of nodes. valid_links = (combinations(set(carrier.keys()), 2) if l is None else set(l)) # And for all of them take the size of the intersection between all their time-sets. return LinkCollection({(u, v): len(carrier[u] & carrier[v]) for u, v in iter(valid_links)}) else: u, v = l if bool(self): idxa, idxb = (self.df.u == u), (self.df.u == v) if idxa.any() and idxb.any(): return self.df[idxa].intersection_size(self.df[idxb]) idxa, idxb = (self.df.u == u), (self.df.u == v) if idxa.any() and idxb.any(): return self.df[idxa].intersection_size(self.df[idxb]) return 0.