我有一个看起来像这样的数据框
pd.DataFrame({'A': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'],
...: 'B': ['C1', 'C1', 'C1', 'C1', 'C2', 'C2', 'C2', 'C2'],
...: 'X': [0, 0, 1, 1, 0, 1, 0, 0],
...: 'Y': [1, 1, 1, 0, 1, 1, 0, 1],
...: 'Z': [4, 5, 2, 1, 2, 1, 3, 5]})
Out[35]:
A B X Y Z
0 A C1 0 1 4
1 B C1 0 1 5
2 C C1 1 1 2
3 D C1 1 0 1
4 E C2 0 1 2
5 F C2 1 1 1
6 G C2 0 0 3
7 H C2 0 1 5
我想按组(B列)选择所有行,其中Y列等于1 AND
(Z列的总和)<(10-X = 1的Z列的总和)
我尝试过
(df.Y==1) & ((df[df.Y==1].groupby('B')['Z'].cumsum()) <= (10 - df[df.X==1].groupby('B')['Z'].sum()))
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2963, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-36-5be310568c09>", line 1, in <module>
df['S'] = (df.Y==1) & ((df[df.Y==1].groupby('B')['Z'].cumsum()) <= (10 - df[df.X==1].groupby('B')['Z'].sum()))
File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\ops\common.py", line 64, in new_method
return method(self, other)
File "C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\ops\__init__.py", line 524, in wrapper
raise ValueError("Can only compare identically-labeled Series objects")
ValueError: Can only compare identically-labeled Series objects
这有效
(df.Y==1) & ((df[df.Y==1].groupby('B')['Z'].cumsum()) <= 10)
Out[39]:
0 True
1 True
2 False
3 False
4 True
5 True
6 False
7 True
dtype: bool
但这只是检查是否(cumsum <= 10),而不是(10减去df.Z,其中df.X == 1)
什么是正确的方法?
答案 0 :(得分:0)
让我们使用groupby().apply()
并使用您的逻辑:
mask = (df.loc[df['Y']==1]
.groupby('B')
.apply(lambda x: x['Z'].cumsum() + x['Z']*x['X'].eq(1) < 10)
.reset_index('B', drop=True)
& df['Y'].eq(1)
)
输出:
0 True
1 True
2 False
3 False
4 True
5 True
6 False
7 True
dtype: bool
答案 1 :(得分:0)
此方法创建2个新列,然后使用其中的值来过滤数据框。新列:
•'Z_cumsum':当'Y'= 1时,按'B'中的组的'Z'累积总和
•'Z_sum':'B'中每个组的Z值之和,仅包括Z其中的值
df['Z_cumsum'] = np.nan
df.loc[df.Y==1, 'Z_cumsum'] = df[df.Y==1].groupby('B')['Z'].cumsum()
df['Z_sum'] = np.nan
for b in set(df['B']):
df.loc[df.B==b,'Z_sum'] = df.loc[df['X']==1].groupby('B')['Z'].sum()[b]
df
新数据框:
A B X Y Z Z_cumsum Z_sum
0 A C1 0 1 4 4.0 3.0
1 B C1 0 1 5 9.0 3.0
2 C C1 1 1 2 11.0 3.0
3 D C1 1 0 1 NaN 3.0
4 E C2 0 1 2 2.0 1.0
5 F C2 1 1 1 3.0 1.0
6 G C2 0 0 3 NaN 1.0
7 H C2 0 1 5 8.0 1.0
现在,您可以更轻松地过滤数据框:
(df.Y==1) & (df['Z_cumsum'] <= (10- df['Z_sum']))
0 True
1 False
2 False
3 False
4 True
5 True
6 False
7 True
dtype: bool
我知道这是一种相当麻烦的方法,但这是我能够得到的。