我有这样的数据
df = pd.DataFrame({'id': [205,205,205, 211, 211, 211]
, 'date': pd.to_datetime(['2019-12-01','2020-01-01', '2020-02-01'
,'2019-12-01' ,'2020-01-01', '2020-03-01'])})
df
id date
0 205 2019-12-01
1 205 2020-01-01
2 205 2020-02-01
3 211 2019-12-01
4 211 2020-01-01
5 211 2020-03-01其中,列date是为id 205连续几个月生成的,而对于id 211则不是。
我只想保留(**id**)的观测值,因为我有每月的数据,没有跳转。在这个例子中,需要:
id date
0 205 2019-12-01
1 205 2020-01-01
2 205 2020-02-01在这里,我收集id以保存:
keep_id = []
for num in pd.unique(df.index):
temp = (df.loc[df['id']==num,'date'].dt.year - df.loc[df['id']==num,'date'].shift(1).dt.year) * 12 + df.loc[df['id']==num,'date'].dt.month - df.loc[df['id']==num,'date'].shift(1).dt.month
temp.values[0] = 1.0 # here I correct the first entry
if (temp==1.).all():
keep_id.append(num)在这里,我使用(df.loc[num,'date'].dt.year - df.loc[num,'date'].shift(1).dt.year) * 12 + df.loc[num,'date'].dt.month - df.loc[num,'date'].shift(1).dt.month来计算每个id与前一个date的几个月之间的差异。
当在一小部分df上测试时,这似乎是可行的,但我确信有一种更好的方法可以做到这一点,也许可以使用.groupby()方法。
由于df 是由数以百万计的观察组成的,所以我的代码花费了太多的时间(我想学习一种更高效、更仿生的方法)
发布于 2020-11-09 17:28:39
您想要做的是使用groupby而不是groupby。
df.groupby('id').filter(lambda x: not (x.date.diff() > pd.Timedelta(days=32)).any())准确地提供:
id date
0 205 2019-12-01
1 205 2020-01-01
2 205 2020-02-01事实上,我会保持指数的独特性,有太多有用的特征需要保留。
在输出方面,这种反应和Michael的上述都是正确的。就性能而言,它们也非常相似:
%timeit df.groupby('id').filter(lambda x: not (x.date.diff() > pd.Timedelta(days=32)).any())
1.48 ms ± 12.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)和
%timeit df[df.groupby('id')['date'].transform(lambda x: x.diff().max() < pd.Timedelta(days=32))]
1.7 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)对于大多数操作来说,这种差异是可以忽略不计的。
发布于 2020-11-09 17:29:19
您可以使用以下方法。在我的测试中只快了3倍。
df[df.groupby('id')['date'].transform(lambda x: x.diff().max() < pd.Timedelta(days=32))]退出:
date
id
205 2019-12-01
205 2020-01-01
205 2020-02-01https://stackoverflow.com/questions/64756014
复制相似问题