Python 熊猫:在N个字符串之后移动
我有数据帧Python 熊猫:在N个字符串之后移动,python,pandas,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
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)
但是我有一个错误。如果像在您的示例中一样,每个“atm\u 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\u id
中不会总是有3倍的行数,因此您可以选择groupby
和apply
。为了说明这一点,我在您的输入中添加了一行atm\u 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\u id
中,每3行就有一个。在这里,不同的解决方案可以使用df
中的上述信息,我的方法是按索引编号,假设您的数据中有唯一的索引编号。创建一个带有原始索引号的掩码
,并使用与上面相同的方法
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
当您更改atm\u id时,您可以看到最后两行之间从4到5的增量,而Period=4
没有3行
注意:如果您的索引不是唯一的,则在开始时使用reset\u index
,在结束时使用set\u index
返回会得到相同的结果,而且我没有像您那样对值进行排序,但这不是问题。您想要的结果不清楚。为什么要3x1
、2x2
、3x3
、2x4
?@NilsWerner谢谢,你说得对。这是我的错误。我已经修好了