根据日期和时间条件创建列

时间:2021-06-28 19:06:59

标签: python pandas

我有一个包含超过 10,000 条记录的交通机构的每日智能卡交易数据集。我正在尝试创建一个名为 transfer 的列,用于指示交易是否为转移。我创建了一个模拟数据集:

mock_df = pd.DataFrame({
    'cardNumber': ['100', '100', '100', '200', '300', '300', '300'],
    'type': ['DAILY_CAP_REACHED', 'DAILY_CAP_REACHED', 'DAILY_CAP_REACHED', 'DAILY_CAP_REACHED',
             'DAILY_CAP_REACHED', 'DAILY_CAP_REACHED', 'DAILY_CAP_REACHED'],
    'date_only': ['2021/05/01', '2021/05/01', '2021/05/01', '2021/05/01', '2021/05/04', '2021/05/04', '2021/05/04'],
    'time_only': ['17:15', '17:45', '18:15', '12:15', '13:15', '17:45', '18:15'],
    'fare': [250, 0, 0, 250, 250, 0, 0]
})

产生下表。

    cardNumber  type                date_only   time_only   fare
0   100         DAILY_CAP_REACHED   2021/05/01  17:15       250
1   100         DAILY_CAP_REACHED   2021/05/01  17:45       0
2   100         DAILY_CAP_REACHED   2021/05/01  18:15       0
3   200         DAILY_CAP_REACHED   2021/05/01  12:15       250
4   300         DAILY_CAP_REACHED   2021/05/04  13:15       250
5   300         DAILY_CAP_REACHED   2021/05/04  17:45       0
6   300         DAILY_CAP_REACHED   2021/05/04  18:15       0

乘客每天有 90 分钟的时间从第一笔交易开始进行转乘。因此,如果自第一次交易以来已经过去了 90 分钟以上,则不应将其记录为转账。 我希望有一个如下所示的数据框:

    cardNumber  type                date_only   time_only   fare   transfer
0   100         DAILY_CAP_REACHED   2021/05/01  17:15       250    N
1   100         DAILY_CAP_REACHED   2021/05/01  17:45       0      Y
2   100         DAILY_CAP_REACHED   2021/05/01  18:15       0      Y
3   200         DAILY_CAP_REACHED   2021/05/01  12:15       250    N
4   300         DAILY_CAP_REACHED   2021/05/04  13:15       250    N
5   300         DAILY_CAP_REACHED   2021/05/04  17:45       0      N
6   300         DAILY_CAP_REACHED   2021/05/04  18:15       0      Y

2 个答案:

答案 0 :(得分:1)

您可以使用:

mock_df['datetime'] = pd.to_datetime(mock_df['date_only'] + ' ' + mock_df['time_only'])

mock_df['transfer'] = np.where(mock_df.groupby('cardNumber')['datetime'].diff() <= pd.Timedelta(minutes=90), 'Y', 'N')

结果:

print(mock_df)

  cardNumber               type   date_only time_only  fare            datetime transfer
0        100  DAILY_CAP_REACHED  2021/05/01     17:15   250 2021-05-01 17:15:00        N
1        100  DAILY_CAP_REACHED  2021/05/01     17:45     0 2021-05-01 17:45:00        Y
2        100  DAILY_CAP_REACHED  2021/05/01     18:15     0 2021-05-01 18:15:00        Y
3        200  DAILY_CAP_REACHED  2021/05/01     12:15   250 2021-05-01 12:15:00        N
4        300  DAILY_CAP_REACHED  2021/05/04     13:15   250 2021-05-04 13:15:00        N
5        300  DAILY_CAP_REACHED  2021/05/04     17:45     0 2021-05-04 17:45:00        N
6        300  DAILY_CAP_REACHED  2021/05/04     18:15     0 2021-05-04 18:15:00        Y

答案 1 :(得分:0)

我正在阅读的关键部分是这个要求:

“如果自第一次交易以来已经过去了 90 分钟以上,则不应将其记录为转账。”

因此,仅与前一次相比是不够的,因为 3 笔交易中的每笔交易之间可能不到 90 分钟,但第一笔和最后一笔之间的时间可能超过 90 分钟,从而使其成为非转移。

这种方法会奏效,尽管可能有办法让它更漂亮一些:

mock_df['datetime'] = pd.to_datetime(mock_df['date_only'] + ' ' + mock_df['time_only'])
for grp_idx,grp in mock_df.groupby('cardNumber'):
    for i,(idx,dt) in enumerate(grp['datetime'].iteritems()):
        if i==0:
            dt_comp = dt
            mock_df.at[idx,'transfer'] = 'N'
        else:
            if dt-dt_comp < pd.Timedelta(minutes=90):
                mock_df.at[idx,'transfer'] = 'Y'
            else:
                mock_df.at[idx,'transfer'] = 'N'
                dt_comp = dt

编辑:添加结果

  cardNumber               type   date_only time_only  fare  \
0        100  DAILY_CAP_REACHED  2021/05/01     17:15   250   
1        100  DAILY_CAP_REACHED  2021/05/01     17:45     0   
2        100  DAILY_CAP_REACHED  2021/05/01     18:15     0   
3        200  DAILY_CAP_REACHED  2021/05/01     12:15   250   
4        300  DAILY_CAP_REACHED  2021/05/04     13:15   250   
5        300  DAILY_CAP_REACHED  2021/05/04     17:45     0   
6        300  DAILY_CAP_REACHED  2021/05/04     18:15     0   

             datetime transfer  
0 2021-05-01 17:15:00        N  
1 2021-05-01 17:45:00        Y  
2 2021-05-01 18:15:00        Y  
3 2021-05-01 12:15:00        N  
4 2021-05-04 13:15:00        N  
5 2021-05-04 17:45:00        N  
6 2021-05-04 18:15:00        Y