Python:Pandas Dataframe如何将整个列与标量相乘


72

如何将数据框给定列的每个元素与标量相乘?(我曾尝试过寻找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熊猫

完整跟踪:

 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。我无法复制该错误,提供完整的追溯也很好。
Leb 2015年

我进行了编辑以添加完整的跟踪记录...也不是错误,而是警告(为清楚起见)
labheshr 2015年

我认为这是由该行以外的其他原因引起的,或者该行导致了之前发出的警告上升。您得到的与切片数据帧有关。
Leb 2015年

很好奇,您曾经想过吗?我正在处理同样的问题。
gammapoint '16

在这段代码之前,您已经过滤了df以减少行数或其他内容。也许您做过df = BigDF.query("X == 1")df = BigDF[BigDF.X == 1]类似的事情,这意味着df实际上只是BigDF上的一个视图。该警告告诉您它正在强迫它进行复制,因为否则会导致BigDF发生更改。
Korone

Answers:


63

尝试使用套用功能。

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

2
与循环相比,这非常优美,尽管我仍然可以看到SettingWithCopyWarning
labheshr 2015年

7
Series.apply是一个循环,不应用于简单的乘法。不必要的lambda只会使情况更糟。
ALollz

53

注意:对于使用熊猫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秒
bilen

从1.0开始,使用Attribute Access进行索引的@ALollz仍在用户指南中,我认为您是指从创建新列开始的警告。的用法在df.col_name = 此处有效
DJK

45

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

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

2
这将在熊猫0.18.0中引发SettingWithCopyWarning。
kadrach '16

8
似乎令人难以置信的是,熊猫中有多少陷阱,而R:中有多容易require(data.table); df[,quantity]*-1。无需记住冒号.ix.lociloc,引用字段名称,也没有更新副本时,你的意思是要更新原有的。
Wassadamo

1
出现错误的真正原因不是代码中包含任何内容:您可以使用iloc,loc或apply。真正的问题是由于如何创建df DataFrame。您很可能在没有使用df的情况下将.copy(). 其创建为另一个DataFrame的切片df = original_df.loc[some slicing].copy()
莎拉

@Sarah是正确的,在对数据帧的一部分进行操作时,此处几乎所有答案都将失败。
大卫·沃特沃思

14

较新的熊猫版本具有pd.DataFrame.multiply函数。

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

7

为什么你得到错误的,真正的问题不在于有什么不对您的代码:您可以使用ilocloc或者apply,或者*=,另一个人可以工作。

真正的问题是由于如何创建df DataFrame。您很可能在没有使用df的情况下将.copy(). 其创建为另一个DataFrame的切片df = original_df.loc[some slicing].copy()

您收到的错误消息中已经说明了问题“ SettingWithCopyWarning:正在尝试从DataFrame的切片副本上设置一个值。尝试改用.loc [row_indexer,col_indexer] = value”
您将得到相同的消息在最新版本的熊猫中也是如此。

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


2
现在,这应该是公认的答案。在前面的切片操作中添加.copy()是防止出现上述警告的关键。
巴登

4

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

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

2

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

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

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



1

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

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

这是唯一提及的有效且不会发出警告的解决方案
Chrisvdberge

1

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

df.quantity = df.quantity  * -1

0

也可以将数字索引与一起使用.iloc

df.iloc[:,0]  *= -1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.