Join two timelines / list of tuples
Question: I have timelines/timeseries which consist of a list of two-tuples where the
first part of the tuple is a timestamp and the second part is the value. The
tuples are ordered by their timestamp.

I now have two of these timelines and need to divide them by each other. This
means that if I got values in both timelines for the same timestamp, I need to
divide them. If there is no value in one of the timelines on the timestamp, 0
should be assumed. If (and only if) a division by zero occurs, NaN should be
assumed. The timestamps have large gaps, which means that iterating from
min(timestamp) to max(timestamp) is not a solution.

I constructed a solution which is both, very unpythonic and has a poor running
time. As the timelines are about a million entries long, performance is
important for me. My solution does not take advantage, that both lists are
sorted.

Is there a better solution, if yes which?

    
    
    #!/usr/bin/env python
    
    l1 = [(1, 100), (2, 1000),           (4, 1500), (5, 5400),          (7, 7800)]
    l2 = [(1, 20),  (2, 400),  (3, 240), (4, 500),  (5, 100),  (6, 27),          ]
    ex = [(1, 5),   (2, 2),    (3, 0),   (4, 3),    (5, 54),   (6, 0),  (7, float('NaN'))]
    
    def f(l1, l2):
      #Turn to dicts:
      l1d = dict(l1)
      l2d = dict(l2)
    
      #Compute Keyspace
      keys = set(l1d.keys()).union(set(l2d.keys()))
    
      result = []
      for key in keys:
        if not key in l2d:
          result.append((key, float('NaN')))
        elif key not in l1d:
          result.append((key, 0))
        else:
          result.append((key, l1d[key]/l2d[key])) 
    
      return result
    
    r = f(l1, l2)
    
    print("L1: %s" % (l1))
    print("L2: %s" % (l2))
    print("")
    print("Expected: %s" % (ex))
    print("Result: %s" % (r))
    


Answer: If performance is needed, have a look at [pandas](http://pandas.pydata.org/):

    
    
    import pandas as pd
    
    l1 = [(1, 100), (2, 1000),           (4, 1500), (5, 5400),          (7, 7800)]
    l2 = [(1, 20),  (2, 400),  (3, 240), (4, 500),  (5, 100),  (6, 27),          ]
    
    s1 = pd.Series(dict(l1))
    s2 = pd.Series(dict(l2))
    

now a very explicit mathematical operation:

    
    
    s1 / s2
    

returns

    
    
    1     5.0
    2     2.5
    3     NaN
    4     3.0
    5    54.0
    6     NaN
    7     NaN
    

If you want to replace `NaN` with zeroes if present in `l2`:

    
    
    s1.reindex(s1.index|s2.index).fillna(0) / s2
    
    
    1     5.0
    2     2.5
    3     0.0
    4     3.0
    5    54.0
    6     0.0
    7     NaN
    

Works perfectly well for million entries as well. You can use datetimes in
index and operate on them datetimecally.

