Pandas,将数据框中的所有数值乘以一个常数。

25

如何将数据框中所有数值型值乘以一个常数,而不必明确指定列名?例如:

In [13]: df = pd.DataFrame({'col1': ['A','B','C'], 'col2':[1,2,3], 'col3': [30, 10,20]})

In [14]: df
Out[14]: 
  col1  col2  col3
0    A     1    30
1    B     2    10
2    C     3    20

我尝试了df.multiply,但它也影响了字符串值,使它们重复多次连接在一起。

In [15]: df.multiply(3)
Out[15]: 
  col1  col2  col3
0  AAA     3    90
1  BBB     6    30
2  CCC     9    60
有没有一种方法可以在仅将数字值乘以常数的情况下保留字符串值不变?

有什么理由避免使用列名吗? - ganesshkumar
大型数据框,包含混合文本和数字字段。@ganesshkumar - CentAu
5个回答

35

您可以使用 select_dtypes() 来选择指定数据类型的列,包括 number 类型,或者排除所有 objectdatetime64 类型的列:

示例:

In [162]: df
Out[162]:
  col1  col2  col3       date
0    A     1    30 2016-01-01
1    B     2    10 2016-01-02
2    C     3    20 2016-01-03

In [163]: df.dtypes
Out[163]:
col1            object
col2             int64
col3             int64
date    datetime64[ns]
dtype: object

In [164]: df.select_dtypes(exclude=['object', 'datetime']) * 3
Out[164]:
   col2  col3
0     3    90
1     6    30
2     9    60

或者一个更好的解决方案 (c) ayhan

df[df.select_dtypes(include=['number']).columns] *= 3

文档中得知:

要选择所有数值类型,请使用numpy数据类型numpy.number


12
要在原始数据框上操作,可以将其修改为:df[df.select_dtypes(include=['number']).columns] *= 3 - ayhan
1
@ayhan,谢谢!我已将您的解决方案添加到我的答案中,这可能会帮助那些不阅读评论的人... :) - MaxU - stand with Ukraine
最近我有一个随意的想法,想问一下:用NumPy函数回答pandas问题是否公平?我的意思是我不介意,但我猜OPs也不会介意,并且他们也可以访问NumPy,至少在安装pandas库时记得安装。此外,由于pandas在内部使用NumPy,这样做是否看起来像是黑客行为/作弊?顺便说一句,我是指我在pandas上的帖子。 - Divakar
3
@Divakar,我非常喜欢你针对pandas问题提供的NumPy解决方案,特别是当它们比原来的解决方案快好几个数量级时。 - MaxU - stand with Ukraine
4
@Divakar OP可以选择任何他们想要的答案。之后,社区中的我们将按照我们的意愿进行投票。我认为你的NumPy技能总是受到欢迎的。 - piRSquared
1
@piRSquared, MaxU,谢谢你们,非常感谢你们的反馈和积极的确认! - Divakar

7
另一个答案指出了如何仅对数字列进行乘法运算。下面是如何更新它的方法:
df = pd.DataFrame({'col1': ['A','B','C'], 'col2':[1,2,3], 'col3': [30, 10,20]})

s = df.select_dtypes(include=[np.number])*3

df[s.columns] = s

print (df)

  col1  col2  col3
0    A     3    90
1    B     6    30
2    C     9    60

4

一种方法是获取 dtypes,将它们与 objectdatetime 的数据类型进行匹配,并使用掩码来排除它们,如下所示 -

df.ix[:,~np.in1d(df.dtypes,['object','datetime'])] *= 3

示例运行 -

In [273]: df
Out[273]: 
  col1  col2  col3
0    A     1    30
1    B     2    10
2    C     3    20

In [274]: df.ix[:,~np.in1d(df.dtypes,['object','datetime'])] *= 3

In [275]: df
Out[275]: 
  col1  col2  col3
0    A     3    90
1    B     6    30
2    C     9    60

3

即使在列内混合类型的情况下,这应该也可以工作,但在大型数据框上可能会很慢。

def mul(x, y):
    try:
        return pd.to_numeric(x) * y
    except:
        return x

df.applymap(lambda x: mul(x, 3))

0

使用assign()select_dtypes()的简单解决方案:

df.assign(**df.select_dtypes('number')*3)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接