同时使用布尔掩码和索引赋值



考虑以下玩具示例:

df = pd.DataFrame([0,1,2,3,4,5,6], columns=['Value'])
df_subset = df.loc[[3,4,5]]
df.loc[df.Value % 2 == 0, 'Value'] = df_subset.Value * 10

df分配前:

0. 0
1. 1
2. 2
3. 3
4. 4
5. 5
6. 6

df分配后:

0. NaN
1. 1
2. NaN
3. 3
4. 40
5. 5
6. NaN

发生这种情况的原因如下:

  • 只有掩码/布尔索引为true的项才会被修改,即只有偶数元素
  • 这就是idx=1未设置为NaN的原因
  • 没有出现在右侧索引中的任何索引都设置为NaN

然而,我想要实现的是相同的行为,而不将丢失的索引项设置为NaN,即

  • 修改掩码为true的元素
  • 对于这些元素:如果特定索引是df.index的一部分,则用df_subset中的值替换df中的值

所需输出:

0. 0
1. 1
2. 2
3. 3
4. 40
5. 5
6. 6

第一个想法是通过&为逐位AND链接两个掩码,因为使用了测试索引Index.isin:

df = pd.DataFrame([0,1,2,3,4,5,6], columns=['Value'])
df_subset = df.loc[[3,4,5]]
mask = (df.Value % 2 == 0) & (df.index.isin([3,4,5]))
df.loc[mask, 'Value'] = df_subset.Value * 10
print (df)
Value
0      0
1      1
2      2
3      3
4     40
5      5
6      6

或者:

df = pd.DataFrame([0,1,2,3,4,5,6], columns=['Value'])
mask = (df.Value % 2 == 0) & (df.index.isin([3,4,5]))
df.loc[mask, 'Value'] *= 10
print (df)
Value
0      0
1      1
2      2
3      3
4     40
5      5
6      6

另一个想法是通过原始掩码过滤子集,并使用DataFrame.update:

df = pd.DataFrame([0,1,2,3,4,5,6], columns=['Value'])
df_subset = df.loc[[3,4,5]]
df.update(df_subset.loc[df.Value % 2 == 0, 'Value'] * 10)
#alternative
#df.update(df_subset.loc[df_subset.Value % 2 == 0, 'Value'] * 10)
print (df)
Value
0    0.0
1    1.0
2    2.0
3    3.0
4   40.0
5    5.0
6    6.0

最新更新