Pandas布尔过滤器,赋值结果为NaN



我很好奇为什么这个在Pandas中同时执行布尔索引+赋值的玩具示例不起作用:

df = pd.DataFrame({'Source': ['A', 'B', 'C', 'A', 'B', 'C'],
'Period': ['1 hr', '1 hr', '1 hr', '24 hr', '24 hr', '24 hr'],
'CO': [1.1, 1.2, 1.3, 2.1, 2.2, 2.3],
'DPM': [11.1, 11.2, 11.3, 12.1, 12.2, 12.3],
'NOx': [21.1, 21.2, 21.3, 22.1, 22.2, 22.3]})

由此产生的玩具DataFrame在这里:

Source Period   CO   DPM   NOx
0      A   1 hr  1.1  11.1  21.1
1      B   1 hr  1.2  11.2  21.2
2      C   1 hr  1.3  11.3  21.3
3      A  24 hr  2.1  12.1  22.1
4      B  24 hr  2.2  12.2  22.2
5      C  24 hr  2.3  12.3  22.3

现在,我希望最终的DataFrame取24 hr值,并将其分配给源A和B的1 hr值。最终的DataFrame应该如下所示:

Source Period   CO   DPM   NOx
0      A   1 hr  2.1  12.1  22.1
1      B   1 hr  2.2  12.2  22.2
2      C   1 hr  1.3  11.3  21.3
3      A  24 hr  2.1  12.1  22.1
4      B  24 hr  2.2  12.2  22.2
5      C  24 hr  2.3  12.3  22.3

我尝试执行以下命令:

df.loc[df['Source'].isin(['A', 'B']) & (df['Period'] == '1 hr'), ['CO', 'DPM', 'NOx']] = 
df.loc[df['Source'].isin(['A', 'B']) & (df['Period'] == '24 hr'), ['CO', 'DPM', 'NOx']]

但最后我的DataFrame被NaNs:取代了

Source Period   CO   DPM   NOx
0      A   1 hr  NaN   NaN   NaN
1      B   1 hr  NaN   NaN   NaN
2      C   1 hr  1.3  11.3  21.3
3      A  24 hr  2.1  12.1  22.1
4      B  24 hr  2.2  12.2  22.2
5      C  24 hr  2.3  12.3  22.3

赋值的LHS和RHS上的筛选器表达式都用相同的行数正确地进行了筛选,似乎赋值就是它被丢弃的地方。我该如何正确地做到这一点?请注意,我只希望CO、DPM和NOx值发生变化,而不希望任何其他列发生变化。

问题是索引不匹配。您可以使用下面的numpy数组来解决这个问题:

msk = (df['Period'] == '24 hr')
cols = ['DPM', 'NOx']
df.loc[~msk & df['Source'].isin(['A','B']), cols] = df.loc[msk & df['Source'].isin(['A','B']), cols].to_numpy()

输出:

Source Period   CO   DPM   NOx
0      A   1 hr  1.1  12.1  22.1
1      B   1 hr  1.2  12.2  22.2
2      C   1 hr  1.3  11.3  21.3
3      A  24 hr  2.1  12.1  22.1
4      B  24 hr  2.2  12.2  22.2
5      C  24 hr  2.3  12.3  22.3

注意,只有当";1小时";以及";24小时";对于每个";来源";类型

您也可以使用groupby+last:

cols = ['DPM', 'NOx']
filt = df['Source'].isin(['A','B'])
df.loc[filt, cols] = df[filt].groupby('Source')[cols].transform('last')

最新更新