如果要满足两个条件,我想屏蔽(或分配'NA')数据帧中列的值。如果条件是按行执行的,则相对简单:
mask = ((df['A'] < x) & (df['B'] < y))
df.loc[mask, 'C'] = 'NA'
但是我在弄清楚如何在数据帧中执行此任务时遇到了一些麻烦,数据帧的结构大致如下:
df = pd.DataFrame({ 'A': (188, 750, 1330, 1385, 188, 750, 810, 1330, 1385),
'B': (2, 5, 7, 2, 5, 5, 3, 7, 2),
'C': ('foo', 'foo', 'foo', 'foo', 'bar', 'bar', 'bar', 'bar', 'bar') })
A B C
0 188 2 foo
1 750 5 foo
2 1330 7 foo
3 1385 2 foo
4 188 5 bar
5 750 5 bar
6 810 3 bar
7 1330 7 bar
8 1385 2 bar
'C' == 'foo'
(类似索引)也应在'C' == 'bar'
时找到“ A”列中的值(尽管它在“ foo”和“ bar”中都可能缺少数据)。如果'foo'和'bar'都小于5或缺少其中的任何一个,如何屏蔽(或分配'NA')列B的行?在上面的示例中,输出将类似于:
A B C
0 188 2 foo
1 750 5 foo
2 1330 7 foo
3 1385 NA foo
4 188 5 bar
5 750 5 bar
6 810 NA bar
7 1330 7 bar
8 1385 NA bar
答案 0 :(得分:2)
这是一个解决方案。这个想法是从两个映射系列m1
和m2
构造两个布尔掩码s1
和s2
。然后使用pd.Series.mask
对系列B
进行遮罩。
# create separate mappings for foo and bar
s1 = df.loc[df['C'] == 'foo'].set_index('A')['B']
s2 = df.loc[df['C'] == 'bar'].set_index('A')['B']
# use -np.inf to cover missing mappings
m1 = df['A'].map(s1).fillna(-np.inf).lt(5)
m2 = df['A'].map(s2).fillna(-np.inf).lt(5)
df['B'] = df['B'].mask(m1 & m2)
print(df)
A B C
0 188 2.0 foo
1 750 5.0 foo
2 1330 7.0 foo
3 1385 NaN foo
4 188 5.0 bar
5 750 5.0 bar
6 810 NaN bar
7 1330 7.0 bar
8 1385 NaN bar
答案 1 :(得分:1)
使用groupby和从jpp的答案中借来的其他一些想法的另一种可能的解决方案:
# create a mapping test for each group from column 'A'
fmap = df.groupby(['A']).apply(lambda x: all(x['B'] < 5))
# and generate a new masking map from that
mask_map = df['A'].map(fmap)
# then just mask the values in the original DF
df['B'] = df['B'].mask(mask_map)
A B C
0 188 2.0 foo
1 750 5.0 foo
2 1330 7.0 foo
3 1385 NaN foo
4 188 5.0 bar
5 750 5.0 bar
6 810 NaN bar
7 1330 7.0 bar
8 1385 NaN bar