熊猫:N弦后移

时间:2018-06-29 09:15:34

标签: python pandas

我有数据框

        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)

但是我有一个错误。

1 个答案:

答案 0 :(得分:0)

如果像您的示例一样,每个“ 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的增量,而当您更改Period=4atm_id没有3行

注意:如果索引不是唯一的,则开头reset_index和结尾set_index的结果相同,同样,我也没有sort_values的意思,但是没问题。