user3600497
user3600497

Reputation: 1661

Find the closest date to a given date

I have an array of datetime objects, and I would like to find which element in the array is the closest to a given date (e.g datetime.datetime(2014,12,16))

This post shows how to find the nearest date which is not before the given date. How can I alter this code so that it can return dates that are before a given date?

For example, if the array housed elements datetime.datetime(2014,12,10) and datetime.datetime(2014,12,28), the former item should be returned because it is closest to datetime.datetime(2014,12,16) in absolute value.

Upvotes: 84

Views: 117172

Answers (9)

Ron Cohen
Ron Cohen

Reputation: 2925

Using numpy is about 2X faster than loop/lambda approaches. all_dates below is a numpy array of dates.

abs_deltas_from_target_date = np.absolute(all_dates - target_date_raw)
index_of_min_delta_from_target_date = np.argmin(abs_deltas_from_target_date)
closest_date = all_dates[index_of_min_delta_from_target_date]

Upvotes: 3

Kevin Zhu
Kevin Zhu

Reputation: 2836

As answered on this link link, 'truncate' function is there for you.

df.truncate(before='2012-01-07')

Or you can use get_loc with 'nearest', 'backfill' or 'ffill' option.

df.iloc[df.index.get_loc(datetime.datetime(2016,2,2),method='nearest')]

Upvotes: 48

Chiel
Chiel

Reputation: 682

This code returns the nearest date before the given date:

def nearest(items, pivot):
    return min([i for i in items if i <= pivot], key=lambda x: abs(x - pivot))

Upvotes: 10

Wes
Wes

Reputation: 35

I know this is an old answer, but I just used the code code that Tamas posted and found that it was taking quite a long time - I optimised it and saw much quicker performance; the problem was the iteration was taking a long time, this is my new method - it will only be quicker when the actual pivot appears in the list

def nearest(items, pivot):
    if pivot in items:
    return pivot
else:
    return min(items, key=lambda x: abs(x - pivot))

Hope this helps anyone who came accross this question.

Upvotes: 2

Tim P
Tim P

Reputation: 425

Assuming you want to answer the slight variant: "Given a dataframe with a datetime index, how do I determine the last value of column col where "last" is defined as the last index that is less than some value date


def last(df, date, col):
    return df.loc[                      # access the dataframe using this index
        max(                            # latest date
            df[df.index < date].index   # that precedes `date`
        )
    ][col]                              # access column `col`

Upvotes: 2

Tamas Hegedus
Tamas Hegedus

Reputation: 29916

This function will return the datetime in items which is the closest to the date pivot.

def nearest(items, pivot):
    return min(items, key=lambda x: abs(x - pivot))

The good part this function works on types other than datetime too out of the box, if the type supports comparison, subtraction and abs, e.g.: numbers and vector types.

Upvotes: 154

Lorenzo Meneghetti
Lorenzo Meneghetti

Reputation: 134

My solution to find the closest index instead of the value

def nearest_ind(items, pivot):
    time_diff = np.abs([date - pivot for date in items])
    return time_diff.argmin(0)

Upvotes: 6

GreenTurtle
GreenTurtle

Reputation: 880

To find a closest date and return the timedelta (difference between two dates) I did the following:

def nearest_date(items,pivot):
    nearest=min(items, key=lambda x: abs(x - pivot))
    timedelta = abs(nearest - pivot)
    return nearest, timedelta

This may be useful when you have a minimum threshold for nearness for your app like I did.

Upvotes: 3

3442
3442

Reputation: 8576

def nearestDate(base, dates):
    nearness = { abs(base.timestamp() - date.timestamp()) : date for date in dates }
    return nearness[min(nearness.keys())]

Upvotes: 1

Related Questions