我有数据框
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)
但是我有一个错误。
答案 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的行数倍,因此可以按groupby
和apply
进行操作。我用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=4
时atm_id
没有3行
注意:如果索引不是唯一的,则开头reset_index
和结尾set_index
的结果相同,同样,我也没有sort_values
的意思,但是没问题。