【问题标题】:Python: Pandas Dataframe how to multiply entire column with a scalarPython:Pandas Dataframe 如何将整列与标量相乘
【发布时间】:2016-02-19 11:37:10
【问题描述】:

如何将数据框给定列的每个元素与标量相乘? (我尝试过查看 SO,但似乎找不到正确的解决方案)

做类似的事情:

df['quantity'] *= -1 # trying to multiply each row's quantity column with -1

给我一​​个警告:

A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

注意:如果可能的话,我不想遍历数据帧并做这样的事情......因为我认为整个列上的任何标准数学运算都应该是可能的,而无需编写循环:

for idx, row in df.iterrows():
    df.loc[idx, 'quantity'] *= -1

编辑

我正在运行 0.16.2 的 Pandas

完整的跟踪:

 SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self.obj[item] = s

【问题讨论】:

  • 使用dtype检查该列的类型。我无法复制该错误,最好提供完整的回溯。
  • 我已经编辑以添加完整的跟踪...这也不是错误,它是警告(为了清楚起见)
  • 我认为它是由该行以外的其他原因引起的,或者该行可能导致之前生成的警告上升。您得到的与切片数据框有关。
  • 很好奇,你有想过这个吗?我正在处理同样的问题。
  • 在这段代码之前的某个时刻,您已经过滤了 df 以减少行数或其他东西。也许你做了df = BigDF.query("X == 1")df = BigDF[BigDF.X == 1] 或类似的东西,这意味着 df 实际上只是 BigDF 的一个视图。警告告诉您它正在强制它进行复制,否则会导致 BigDF 发生变化。

标签: python pandas chained-assignment


【解决方案1】:

还可以在.iloc 中使用数字索引。

df.iloc[:,0]  *= -1

【讨论】:

    【解决方案2】:

    您收到错误的真正问题不在于您的代码有什么问题:您可以使用iloclocapply*=,其中另一个可以已经工作了。

    您遇到的真正问题是由于您创建 df DataFrame 的方式。很可能您将 df 创建为另一个 DataFrame 的切片而不使用 .copy(). 将 df 创建为另一个 DataFrame 的切片的正确方法是 df = original_df.loc[some slicing].copy()

    您收到的错误消息“ SettingWithCopyWarning: 试图在 DataFrame 中的切片副本上设置值。 尝试改用 .loc[row_indexer,col_indexer] = value"
    在最新版本的 pandas 中,您也会收到相同的信息。

    每当您收到此类错误消息时,都应始终检查您是如何创建 DataFrame 的。您可能忘记了.copy()

    【讨论】:

    • 这现在应该是公认的答案。在前面的切片操作中添加 .copy() 是防止上述警告的关键。
    【解决方案3】:

    您可以使用要应用乘法的列的索引

    df.loc[:,6] *= -1
    

    这会将索引为 6 的列乘以 -1。

    【讨论】:

      【解决方案4】:

      游戏有点晚了,但对于未来的搜索者来说,这也应该有用:

      df.quantity = df.quantity  * -1
      

      【讨论】:

        【解决方案5】:

        最近的 pandas 版本具有 pd.DataFrame.multiply 函数。

        df['quantity'] = df['quantity'].multiply(-1)
        

        【讨论】:

          【解决方案6】:

          注意:对于那些使用 pandas 0.20.3 及更高版本并正在寻找答案的人,所有这些选项都将起作用:

          df = pd.DataFrame(np.ones((5,6)),columns=['one','two','three',
                                                 'four','five','six'])
          df.one *=5
          df.two = df.two*5
          df.three = df.three.multiply(5)
          df['four'] = df['four']*5
          df.loc[:, 'five'] *=5
          df.iloc[:, 5] = df.iloc[:, 5]*5
          

          导致

             one  two  three  four  five  six
          0  5.0  5.0    5.0   5.0   5.0  5.0
          1  5.0  5.0    5.0   5.0   5.0  5.0
          2  5.0  5.0    5.0   5.0   5.0  5.0
          3  5.0  5.0    5.0   5.0   5.0  5.0
          4  5.0  5.0    5.0   5.0   5.0  5.0
          

          【讨论】:

          • 我试过了,我的分配运行了 1.2 秒,现在运行了 0.05 秒
          【解决方案7】:

          我在使用 Pandas 0.22 时收到此警告。您可以通过使用assign 方法非常明确地避免这种情况:

          df = df.assign(quantity = df.quantity.mul(-1))
          

          【讨论】:

          • 这是唯一提到的有效且不会发出警告的解决方案
          【解决方案8】:

          有点旧,但我仍然得到相同的 SettingWithCopyWarning。这是我的解决方案:

          df.loc[:, 'quantity'] = df['quantity'] * -1
          

          【讨论】:

            【解决方案9】:

            经过一番研究,这是答案:

            df.loc[:,'quantity'] *= -1 #seems to prevent SettingWithCopyWarning 
            

            【讨论】:

            • 这会在 pandas 0.18.0 中引发 SettingWithCopyWarning。
            • 似乎在 Pandas 中有多少陷阱,而在 R 中要容易得多:require(data.table); df[,quantity]*-1。无需记住冒号、.ix.lociloc、引用字段名称,也无需在您打算更新原始文件时更新副本。
            • 您收到错误的真正问题不在于您的代码有任何问题:您可以使用 iloc、loc 或 apply。您遇到的真正问题是由于您创建 df DataFrame 的方式。很可能您将 df 创建为另一个 DataFrame 的切片而不使用 .copy(). 将 df 创建为另一个 DataFrame 的切片的正确方法是 df = original_df.loc[some slicing].copy()
            • @Sarah 是正确的,这里的几乎所有答案在对数据帧的切片进行操作时都会失败。
            • @Sarah 您的解释很清楚,使用copy() 后确实不会发生错误。 但是,即使我修改了没有copy()dforiginal_df没有被修改。这是为什么呢?
            【解决方案10】:

            尝试使用应用功能。

            df['quantity'] = df['quantity'].apply(lambda x: x*-1)
            

            【讨论】:

            • 与循环相比,这非常优雅,尽管我仍然得到 SettingWithCopyWarning
            • Series.apply 是一个循环,不应用于简单的乘法。不必要的 lambda 只会让事情变得更糟。
            • @ALollz 你有什么替代方案?
            【解决方案11】:

            试试df['quantity'] = df['quantity'] * -1

            【讨论】:

            • 这与 df['quantity'] *= -1 没有什么不同(是的,我得到了同样的警告)
            猜你喜欢
            • 2018-08-28
            • 1970-01-01
            • 2012-11-18
            • 1970-01-01
            • 2021-11-20
            • 1970-01-01
            • 2011-11-13
            • 1970-01-01
            • 2023-03-22
            相关资源
            最近更新 更多