1
1
"""Time dependent algorithms."""
2
2
3
- from datetime import datetime , timedelta
4
-
5
3
import networkx as nx
6
4
from networkx .utils import not_implemented_for
7
5
11
9
@not_implemented_for ("undirected" )
12
10
@not_implemented_for ("multigraph" )
13
11
@nx ._dispatch (node_attrs = {"time" : None , "weight" : 1 })
14
- def cd_index (G , node , * , time_delta = timedelta ( days = 5 * 365 ) , time = "time" , weight = None ):
12
+ def cd_index (G , node , time_delta , * , time = "time" , weight = None ):
15
13
r"""Compute the CD index for `node` within the graph `G`.
16
14
17
15
Calculates the CD index for the given node of the graph,
@@ -26,12 +24,15 @@ def cd_index(G, node, *, time_delta=timedelta(days=5 * 365), time="time", weight
26
24
`weight` attributes (if a weight is not given, it is considered 1).
27
25
node : node
28
26
The node for which the CD index is calculated.
29
- time_delta : timedelta, integer or float (Optional, default is timedelta(days=5*365))
30
- Amount of time after the `time` attribute of the `node`.
27
+ time_delta : numeric or timedelta
28
+ Amount of time after the `time` attribute of the `node`. The value of
29
+ `time_delta` must support comparison with the `time` node attribute. For
30
+ example, if the `time` attribute of the nodes are `datetime.datetime`
31
+ objects, then `time_delta` should be a `datetime.timedelta` object.
31
32
time : string (Optional, default is "time")
32
33
The name of the node attribute that will be used for the calculations.
33
34
weight : string (Optional, default is None)
34
- the name of the node attribute used as weight.
35
+ The name of the node attribute used as weight.
35
36
36
37
Returns
37
38
-------
@@ -50,6 +51,7 @@ def cd_index(G, node, *, time_delta=timedelta(days=5 * 365), time="time", weight
50
51
51
52
Examples
52
53
--------
54
+ >>> from datetime import datetime, timedelta
53
55
>>> G = nx.DiGraph()
54
56
>>> nodes = {
55
57
... 1: {"time": datetime(2015, 1, 1)},
@@ -61,7 +63,19 @@ def cd_index(G, node, *, time_delta=timedelta(days=5 * 365), time="time", weight
61
63
>>> G.add_nodes_from([(n, nodes[n]) for n in nodes])
62
64
>>> edges = [(1, 3), (1, 4), (2, 3), (3, 4), (3, 5)]
63
65
>>> G.add_edges_from(edges)
64
- >>> cd = nx.cd_index(G, 3, time="time", weight="weight")
66
+ >>> delta = timedelta(days=5 * 365)
67
+ >>> nx.cd_index(G, 3, time_delta=delta, time="time")
68
+ 0.5
69
+ >>> nx.cd_index(G, 3, time_delta=delta, time="time", weight="weight")
70
+ 0.12
71
+
72
+ Integers can also be used for the time values:
73
+ >>> node_times = {1: 2015, 2: 2012, 3: 2010, 4: 2008, 5: 2014}
74
+ >>> nx.set_node_attributes(G, node_times, "new_time")
75
+ >>> nx.cd_index(G, 3, time_delta=4, time="new_time")
76
+ 0.5
77
+ >>> nx.cd_index(G, 3, time_delta=4, time="new_time", weight="weight")
78
+ 0.12
65
79
66
80
Notes
67
81
-----
@@ -80,6 +94,14 @@ def cd_index(G, node, *, time_delta=timedelta(days=5 * 365), time="time", weight
80
94
of forward citations in `i` and `w_{it}` is a matrix of weight for patent `i`
81
95
at time `t`.
82
96
97
+ The `datetime.timedelta` package can lead to off-by-one issues when converting
98
+ from years to days. In the example above `timedelta(days=5 * 365)` looks like
99
+ 5 years, but it isn't because of leap year days. So it gives the same result
100
+ as `timedelta(days=4 * 365)`. But using `timedelta(days=5 * 365 + 1)` gives
101
+ a 5 year delta **for this choice of years** but may not if the 5 year gap has
102
+ more than 1 leap year. To avoid these issues, use integers to represent years,
103
+ or be very careful when you convert units of time.
104
+
83
105
References
84
106
----------
85
107
.. [1] Funk, Russell J., and Jason Owen-Smith.
@@ -99,7 +121,7 @@ def cd_index(G, node, *, time_delta=timedelta(days=5 * 365), time="time", weight
99
121
except :
100
122
raise nx .NetworkXError (
101
123
"Addition and comparison are not supported between 'time_delta' "
102
- "and 'time' types, default time_delta = datetime.timedelta ."
124
+ "and 'time' types."
103
125
)
104
126
105
127
# -1 if any edge between node's predecessors and node's successors, else 1
0 commit comments