我有以下数据框架
df = pd.DataFrame([[1990,7,1000],[1990,8,2500],[1990,9,2500],[1990,9,1500],[1991,1,250],[1991,2,350],[1991,3,350],[1991,7,450]], columns = ['year','month','data1'])
year month data1
1990 7 1000
1990 8 2500
1990 9 2500
1990 9 1500
1991 1 250
1991 2 350
1991 3 350
1991 7 450我想对数据进行过滤,这样它就不会包含07/1990、08/1990和01/1991月/年的数据。我可以为每个组合月/年做如下:
df = df.loc[(df.year != 1990) | (df.month != 7)]但是,如果有许多组合,月份/年,这是没有效率的。有没有更有效的方法来做到这一点?
非常感谢。
发布于 2020-12-27 15:37:19
你可以这样做:
mask = ~df[['year', 'month']].apply(tuple, 1).isin([(1990, 7), (1990, 8), (1991, 1)])
print(df[mask])输出
year month data1
2 1990 9 2500
3 1990 9 1500
5 1991 2 350
6 1991 3 350
7 1991 7 450发布于 2020-12-27 15:44:58
甚至更快(大约是应用tuple的优雅版@DaniMesejo的3倍)。但是,它也依赖于这样一种知识,即月份限制在(远低于) 100,因此不那么具有普遍性:
mask = ~(df.year*100 + df.month).isin({199007, 199008, 199101})
df[mask]
# out:
year month data1
2 1990 9 2500
3 1990 9 1500
5 1991 2 350
6 1991 3 350
7 1991 7 450为什么这比元组解决方案快3倍?(速度技巧):
所有向量化操作和无apply.
.isin()和设置作为参数(而不是列表)。发布于 2020-12-27 16:58:52
让我们试试merge
out = df.drop(df.reset_index().merge(pd.DataFrame({'year':[1990,1990,1991],'month':[7,8,1]}))['index'])
year month data1
2 1990 9 2500
3 1990 9 1500
5 1991 2 350
6 1991 3 350
7 1991 7 450和小小的改进
out = df.merge(pd.DataFrame({'year':[1990,1990,1991],'month':[7,8,1]}),indicator=True,how='left').loc[lambda x : x['_merge']=='left_only']
year month data1 _merge
2 1990 9 2500 left_only
3 1990 9 1500 left_only
5 1991 2 350 left_only
6 1991 3 350 left_only
7 1991 7 450 left_only根据我的测试,这应该比使用元组方法更快~
https://stackoverflow.com/questions/65467349
复制相似问题