check if timestamp column is in date range from another dataframe

Issue

I have a dataframe, df_A with two columns ‘amin’ and ‘amax’, which is a set of time range.

My objective is to find whether a column in df_B lies between any of the rows of range in df_A ‘amin’ and ‘amax’ columns.

df_A[['amin','amax'] ]

                  amin                   amax
          0 2016-07-16 19:37:03   2016-07-17 11:16:32
          1 2016-07-04 21:15:54   2016-07-05 10:57:46
          2 2016-07-24 23:30:41   2016-07-25 15:38:02
          3 2016-07-12 03:02:38   2016-07-12 22:11:01

df_B['created_date']

      created_date
   2016-07-17 01:16:32 
   2016-07-05 10:15:54  
   2016-07-12 12:11:01


df_A['amin'] = pd.to_datetime(df_A['amin'], errors='coerce')
df_A['amax'] = pd.to_datetime(df_A['amax'], errors='coerce')
df_B['created_date'] = pd.to_datetime(df_B['created_date'],errors='coerce')

def dt2epoch(value):
   epoch = (value - pd.to_datetime(datetime(2015,12,31).strftime('%Y-%m-%d %H:%M:%S.%f'))).total_seconds()
   return epoch    

df_A['amax_epoch']=df_A['amax'].apply(dt2epoch)
df_A['amin_epoch']=df_A['amin'].apply(dt2epoch)
df_B['created_date_epoch']=df_B['created_date'].apply(dt2epoch)


def make_tuple(row):
     n= len(row)
     row = [(x,row[n - 1]) for x in row]
     return row

minMaxTuple = minMax.apply(make_tuple, axis =1)

Above is part of my code, I’ve tried below(not sure if it’s necessary):

  1. convert them to epoch values
  2. convert df_A into a tuple.

However, df_A and df_B has a different number of rows. Also, I dont have any id column to merge them together.

label = []

for l in df_B['created_date_epoch']:

    if (m[0] for m in minMaxTuple) <= l <= (m[1] for m in minMaxTuple):
        label.append('1')
    else:
        label.append('0')

However, when I run this, the result I get for ‘label’ is an empty list.

Also, the label should be a column that has the same number of rows as df_A.

Ultimately, I would like to add a new ‘label’ column in df_A:

                              minMaxTuple                      label
            (2016-07-16 19:37:03, 2016-07-17 11:16:32)            1
            (2016-07-04 21:15:54, 2016-07-05 10:57:46)            1 
            (2016-07-24 23:30:41, 2016-07-25 15:38:02)            0
            (2016-07-12 03:02:38, 2016-07-12 22:11:01)            1

Solution

One solution would be to see if a created_date in df_b falls between an amin and amax would be to use boolean logic. In a row-wise calculation for each row in df_a you could use the following logic:

if sum((row['amin'] > df_b['created_date']) | (row['amax'] < df_b['created_date'])) == len(df_b)

In this stament I am using the logical operator | to check if amin is less than created_date OR if amax is less than created_date. If the statement is True you could conclude that a created date does not fall between the time period created by amin and amax. If none of the created_dates fall between the period created by amin and amax, you could then assign a value of 0 to df_a['label']: Something like:

import pandas as pd
from StringIO import StringIO

def myfunc(row, df_b):
    if sum((row['amin'] > df_b['created_date']) | (row['amax'] < df_b['created_date'])) == len(df_b):
        return 0
    else:
        return 1

a_str= """
amin,amax
2016-07-16 19:37:03,2016-07-17 11:16:32
2016-07-04 21:15:54,2016-07-05 10:57:46
2016-07-24 23:30:41,2016-07-25 15:38:02
2016-07-12 03:02:38,2016-07-12 22:11:01"""

b_str = """
created_date
2016-07-17 01:16:32 
2016-07-05 10:15:54  
2016-07-12 12:11:01"""
df_a = pd.read_csv(StringIO(a_str), sep=',')
df_b = pd.read_csv(StringIO(b_str), sep=',')

#Convert to datetime
df_a['amin'] = pd.to_datetime(df_a['amin'])
df_a['amax'] = pd.to_datetime(df_a['amax'])
df_b['created_date'] = pd.to_datetime(df_b['created_date'])

df_a['label'] = df_a.apply(lambda x: myfunc(x,df_b), axis=1)

Which returns a column label in df_a with the expected output of:

                 amin                amax  label
0 2016-07-16 19:37:03 2016-07-17 11:16:32      1
1 2016-07-04 21:15:54 2016-07-05 10:57:46      1
2 2016-07-24 23:30:41 2016-07-25 15:38:02      0
3 2016-07-12 03:02:38 2016-07-12 22:11:01      1

Answered By – dubbbdan

Answer Checked By – Pedro (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.