簡體   English   中英

從列表中查找最接近給定日期且不晚於給定日期的日期

[英]Find the closest date from a list to a given date that is not after the given date

我有一個 dataframe 用於每周的培訓課程,還有一個數據框架用於參加者在這些培訓課程中提交的評估。

每個 dataframe 都有一個日期列 - 對於會話,它是 session 發生的日期。 對於評估,這是提交評估的日期。 預計與會者將參加多個會議,因此將提交多個評估。

我需要將每個評估與特定的 session 聯系起來。他們可能在與 session 同一天提交了評估,在這種情況下匹配很容易。 但他們可以在下一次培訓 session 之前的任何一天提交評估。

對於評估 df 中的每個日期,我需要返回最接近評估日期但不晚於評估日期的 session 日期。

例如 session 日期:2/3/22、2/10/22、2/17/22

示例評估日期與所需的 output:2/3/22(應匹配 2/3/22)、2/4/22(應匹配 2/3/22)、2/11/22(應匹配 2/10/22 )

這是一種方法。

sessions dataframe 中,將date列設置為索引:

sessions = sessions.set_index('date')

按索引(即按日期)對會話進行排序:

sessions = sessions.loc[sessions.index.sort_values()]

session_evaluated列添加到評估中,其中將包含評估適用的 session 的日期。 我們通過首先在評估的date列上調用sessions.index.get_indexer()並將method參數設置為“pad”來計算這一點,因此我們在不匹配的日期上“向下舍入”,然后查找這些 integer 索引值在會話索引中(包含 session 日期):

evaluations['session_evaluated'] = pd.Series([sessions.index.to_list()[i] 
    for i in sessions.index.get_indexer(evaluations['date'], method='pad')])

這是將所有內容與示例輸入放在一起的樣子:

import pandas as pd
sessions = pd.DataFrame({
    'date' : ['2022-02-01', '2022-03-01', '2022-04-01', '2022-05-01', '2022-01-01'],
    'topic' : ['Easy 1', 'Easy 2', 'Intermediate', 'Advanced', 'Intro']
})
evaluations = pd.DataFrame({
    'date' : [
        '2022-01-05', '2022-01-10', '2022-01-15', '2022-01-20', '2022-01-25', 
        '2022-02-01', '2022-02-05', '2022-02-28',
        '2022-03-01', '2022-03-15', '2022-03-31',
        '2022-04-01', '2022-04-15'
    ],
    'rating' : [9,8,7,8,9,5,4,3,10,10,10,2,4]
})
sessions['date'] = pd.to_datetime(sessions['date'])
evaluations['date'] = pd.to_datetime(evaluations['date'])
sessions = sessions.set_index('date')
sessions = sessions.loc[sessions.index.sort_values()]
print(sessions)
print(evaluations)
evaluations['session_evaluated'] = pd.Series([sessions.index.to_list()[i]
    for i in sessions.index.get_indexer(evaluations['date'], method='pad')])
print(evaluations)

結果:

                   topic
date
2022-01-01         Intro
2022-02-01        Easy 1
2022-03-01        Easy 2
2022-04-01  Intermediate
2022-05-01      Advanced
         date  rating
0  2022-01-05       9
1  2022-01-10       8
2  2022-01-15       7
3  2022-01-20       8
4  2022-01-25       9
5  2022-02-01       5
6  2022-02-05       4
7  2022-02-28       3
8  2022-03-01      10
9  2022-03-15      10
10 2022-03-31      10
11 2022-04-01       2
12 2022-04-15       4
         date  rating session_evaluated
0  2022-01-05       9        2022-01-01
1  2022-01-10       8        2022-01-01
2  2022-01-15       7        2022-01-01
3  2022-01-20       8        2022-01-01
4  2022-01-25       9        2022-01-01
5  2022-02-01       5        2022-02-01
6  2022-02-05       4        2022-02-01
7  2022-02-28       3        2022-02-01
8  2022-03-01      10        2022-03-01
9  2022-03-15      10        2022-03-01
10 2022-03-31      10        2022-03-01
11 2022-04-01       2        2022-04-01
12 2022-04-15       4        2022-04-01

更新:

這是使用merge_asof() function 的另一種方法。它不需要日期列作為索引(盡管它確實要求 dataframe arguments 都按date排序):

sessions['date'] = pd.to_datetime(sessions['date'])
evaluations['date'] = pd.to_datetime(evaluations['date'])
evaluations = pd.merge_asof(
    evaluations.sort_values(by=['date']), 
    sessions.sort_values(by=['date'])['date'].to_frame().assign(session_evaluated=sessions['date']), 
    on='date')
print(evaluations)

Output:

         date  rating session_evaluated
0  2022-01-05       9        2022-01-01
1  2022-01-10       8        2022-01-01
2  2022-01-15       7        2022-01-01
3  2022-01-20       8        2022-01-01
4  2022-01-25       9        2022-01-01
5  2022-02-01       5        2022-02-01
6  2022-02-05       4        2022-02-01
7  2022-02-28       3        2022-02-01
8  2022-03-01      10        2022-03-01
9  2022-03-15      10        2022-03-01
10 2022-03-31      10        2022-03-01
11 2022-04-01       2        2022-04-01
12 2022-04-15       4        2022-04-01

更新#2:上面代碼中對assign()的調用也可以使用**kwargs語法來編寫,以防我們想要使用帶空格的列名或者不是有效的 python 標識符(而不是session_evaluated )。 例如:

evaluations = pd.merge_asof(
    evaluations.sort_values(by=['date']), 
    sessions.sort_values(by=['date'])['date'].to_frame()
        .assign(**{'Evaluated Session (Date)' : lambda x: sessions['date']}), 
    on='date')

Output:

         date  rating Evaluated Session (Date)
0  2022-01-05       9               2022-01-01
1  2022-01-10       8               2022-01-01
2  2022-01-15       7               2022-01-01
3  2022-01-20       8               2022-01-01
4  2022-01-25       9               2022-01-01
5  2022-02-01       5               2022-02-01
6  2022-02-05       4               2022-02-01
7  2022-02-28       3               2022-02-01
8  2022-03-01      10               2022-03-01
9  2022-03-15      10               2022-03-01
10 2022-03-31      10               2022-03-01
11 2022-04-01       2               2022-04-01
12 2022-04-15       4               2022-04-01

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM