遍历行时如何使用掩码更新 DataFrame 中的值

How do I update value in DataFrame with mask when iterating through rows

使用下面的代码,我试图在触发 if 语句并放置预测时将列 df_test['placed'] 更新为 = 1。不过,我无法让它正确更新,代码编译但不会更新为 = 1 对于放置的相应预测。

df_test['placed'] = np.zeros(len(df_test))
for i in set(df_test['id']) :
    mask = df_test['id']==i
    predictions = lm.predict(X_test[mask])
    j = np.argmax(predictions)
    if predictions[j] > 0 :
        df_test['placed'][mask][j] = 1
        print(df_test['placed'][mask][j])

回答您的问题

编辑:根据评论更改了建议

代码的赋值部分 df_test['placed'][mask][j] = 1 使用所谓的 chained indexing。简而言之,您的作业仅更改立即丢弃的 DataFrame 的临时副本,而不会更改原始 DataFrame。

为避免这种情况,赋值时的经验法则是:在单个 DataFrame 上仅使用一组方括号。对于您的问题,应该如下所示:

df_test.loc[mask.nonzero()[0][j], 'placed'] = 1

(我知道 mask.nonzero() 使用两组方括号;实际上 nonzero() returns 一个元组,该元组的第一个元素是一个 ndarray .但是dataframe只用了一组,那才是最重要的部分。)

其他一些注意事项

我有一些关于使用 pandas (& numpy) 的笔记。

  • Pandas 和 NumPy 都有一个叫做 广播 的特性。基本上,如果您要为整个数组分配一个值,则不需要先创建一个相同大小的数组;您可以只分配单个值,pandas/NumPy 会自动为您计算出如何应用它。所以你的代码的第一行可以用df_test['placed'] = 0代替,它完成同样的事情。

  • 一般来说 在使用 pandas & numpy 对象时,循环不好;通常你可以找到一种方法来使用广播逐元素操作布尔索引的某种组合做一个循环会做的事情。由于这些功能的设计方式,它 运行 也会快很多。不幸的是,我对 lm.predict 方法不够熟悉,但您可以完全避免此代码的整个 for 循环。