Pandas:在N个字符串之后移动

2024-10-01 11:27:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有数据帧

        atm_id     dNDCSessionTime  sCardNumber  nTrRequestCount  
152865       0 2017-01-14 07:56:17            1                1   
153052       0 2017-01-14 08:01:13            1                1   
153053       0 2017-01-14 08:02:19            1                1   
153054       0 2017-01-14 08:03:41            1                1   
152804       0 2017-01-14 08:04:37            1                1   
152805       0 2017-01-14 08:05:24            1                1   
152806       1 2017-01-14 08:06:08            1                1   
152807       1 2017-01-14 08:07:15            1                1   
152808       1 2017-01-14 08:08:08            1                1   
152866       1 2017-01-14 08:08:50            1                1   

我需要添加新的列,也就是说,周期(对于每个atm_id,每3个事务(数据帧中的字符串))

期望输出

            atm_id     dNDCSessionTime  sCardNumber  nTrRequestCount period
152865       0 2017-01-14 07:56:17            1                1      1
153052       0 2017-01-14 08:01:13            1                1      1
153053       0 2017-01-14 08:02:19            1                1      1
153054       0 2017-01-14 08:03:41            1                1      2
152804       0 2017-01-14 08:04:37            1                1      2
152805       0 2017-01-14 08:05:24            1                1      2
152806       1 2017-01-14 08:06:08            1                1      3
152807       1 2017-01-14 08:07:15            1                1      3
152808       1 2017-01-14 08:08:08            1                1      3
152866       1 2017-01-14 08:08:50            1                1      4

我试着用它来做这件事

df['period'] = df.sort_values(['atm_id', 'dNDCSessionTime']).groupby('atm_id').shift(500)

但我有个错误


Tags: 数据字符串iddfshift错误sort事务
1条回答
网友
1楼 · 发布于 2024-10-01 11:27:31

如果像在您的示例中一样,每个“atm_id”的行数是3的倍数,那么您可以使用iloc[::3]来选择每3行

# initiate the column
df['Period'] = None
# select every three rows and assign 1 there in the column Period
df['Period'].iloc[::3] = 1
# use cumsum, ffill and astype to populate an incremental value every 3 rows
df['Period'] = df['Period'].cumsum().ffill().astype(int)

现在,我假设在一个atm_id中不会总是有许多行是3的倍数,所以可以通过groupbyapply来进行。我用atm_id = 2在您的输入中添加了一行来说明这一点。如果您这样做:

print (df.groupby('atm_id').apply(lambda x: x.iloc[::3]))

               atm_id     dNDCSessionTime  sCardNumber  nTrRequestCount Period
atm_id                                                                        
0      152865       0 2017-01-14 07:56:17            1                1   None
       153054       0 2017-01-14 08:03:41            1                1   None
1      152806       1 2017-01-14 08:06:08            1                1   None
       152866       1 2017-01-14 08:08:50            1                1   None
2      152887       2 2017-01-12 07:56:17            1                1   None

因此,在同一个atm_id中每3行就得到一次。在这里,不同的解决方案可以使用df中的上述信息,我的方法是按索引编号,假设您的数据中有唯一的。创建一个带有原始索引号的mask,并使用与上面相同的方法

mask_index = df.groupby('atm_id').apply(lambda x: x.iloc[::3]).index.get_level_values(1)
#if you do print (mask_index), you get
#Out[35]: Int64Index([152865, 153054, 152806, 152866, 152887], dtype='int64')

# initiate the column
df['Period'] = None
# select every three rows within a same atm_id and assign 1 there in the column Period
df.loc[mask_index, 'Period'] = 1
# use cumsum, ffill and astype to populate have an incremental value every 3 rows
df['Period'] = df['Period'].cumsum().ffill().astype(int)

结果是

        atm_id     dNDCSessionTime  sCardNumber  nTrRequestCount  Period
152865       0 2017-01-14 07:56:17            1                1       1
153052       0 2017-01-14 08:01:13            1                1       1
153053       0 2017-01-14 08:02:19            1                1       1
153054       0 2017-01-14 08:03:41            1                1       2
152804       0 2017-01-14 08:04:37            1                1       2
152805       0 2017-01-14 08:05:24            1                1       2
152806       1 2017-01-14 08:06:08            1                1       3
152807       1 2017-01-14 08:07:15            1                1       3
152808       1 2017-01-14 08:08:08            1                1       3
152866       1 2017-01-14 08:08:50            1                1       4
152887       2 2017-01-12 07:56:17            1                1       5

其中,您可以看到最后两行之间从4到5的增量,而更改atm_idPeriod=4没有3行

注意:如果您的索引不是唯一的,那么开头的reset_index和结尾的set_index返回将给出相同的结果,而且我没有像您那样sort_values,但这不是问题

相关问题 更多 >