Python 应用带多个参数的函数创建新列
我想通过对两个现有列应用函数,在Python 应用带多个参数的函数创建新列,python,pandas,Python,Pandas,我想通过对两个现有列应用函数,在pandas数据框中创建一个新列。在此之后,当我只需要一列作为参数时,我就能够创建一个新列: import pandas as pd df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]}) def fx(x): return x * x print(df) df['newcolumn'] = df.A.apply(fx) print(df) 但是,当函数需要多个参数时,我不知道如何执行相同的操作
pandas
数据框中创建一个新列。在此之后,当我只需要一列作为参数时,我就能够创建一个新列:
import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
def fx(x):
return x * x
print(df)
df['newcolumn'] = df.A.apply(fx)
print(df)
但是,当函数需要多个参数时,我不知道如何执行相同的操作。例如,如何通过将列a和列B传递给下面的函数来创建新列
def fxy(x, y):
return x * y
这就解决了问题:
df['newcolumn'] = df.A * df.B
你也可以这样做:
def fab(row):
return row['A'] * row['B']
df['newcolumn'] = df.apply(fab, axis=1)
如果可以重写函数,可以使用@greenAfrican示例。但如果不想重写函数,可以将其包装到apply中的匿名函数中,如下所示:
>>> def fxy(x, y):
... return x * y
>>> df['newcolumn'] = df.apply(lambda x: fxy(x['A'], x['B']), axis=1)
>>> df
A B newcolumn
0 10 20 200
1 20 30 600
2 30 10 300
或者,您可以使用numpy基础函数:
>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
A B new_column
0 10 20 200
1 20 30 600
2 30 10 300
def fab(row):
return row['A'] * row['B'], row['A'] + row['B']
或在一般情况下矢量化任意函数:
>>> def fx(x, y):
... return x*y
...
>>> df['new_column'] = np.vectorize(fx)(df['A'], df['B'])
>>> df
A B new_column
0 10 20 200
1 20 30 600
2 30 10 300
还有一个dict风格的干净语法:
df["new_column"] = df.apply(lambda x: x["A"] * x["B"], axis = 1)
或者
如果需要同时创建多个列:
import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
A B new_column
0 10 20 200
1 20 30 600
2 30 10 300
def fab(row):
return row['A'] * row['B'], row['A'] + row['B']
df['newcolumn'], df['newcolumn2'] = zip(*df.apply(fab, axis=1))
这个答案解决了这个玩具示例,足以让我重写我的实际函数,但它没有说明如何在不重写引用列的情况下应用先前定义的函数。请注意,向量化操作(第一个代码示例)比使用
apply
的代码示例具有更好的性能。感谢您的回答!我很好奇,这是最快的解决方案吗?使用np.vectorize()
的矢量化版本速度惊人。谢谢。这是一个有用的解决方案。如果函数x和y的输入参数的大小不相等,则会出现错误。在这种情况下,@RomanPekar解决方案可以毫无问题地工作。我没有比较性能。我知道这是一个古老的答案,但是:我有一个边缘情况,在这种情况下,np.vectorize
不起作用。原因是,其中一列的类型为pandas._libs.tslibs.timestamps.Timestamp
,通过矢量化将其转换为类型numpy.datetime64
。这两种类型不可互换,导致功能表现不好。有什么建议吗?(除了。应用,因为这显然是要避免的)伟大的解决方案!如果有人想知道vectorize对于字符串比较函数也能运行得很好,而且速度非常快。这是一个很好的技巧,它将列引用保留在apply调用附近(实际上是在其中)。我使用这个技巧和提供的多列输出技巧@toto_tico生成了一个3列输入,4列输出的函数!很好!哇,看来你是唯一一个不关注OP的简单示例,但解决了整个问题的人,谢谢,这正是我需要的!:)事实上,这应该是“官方”答案。我想知道如何用一个apply生成多个列!我用@Roman Pekar的答案生成了一个3列输入,4列输出的函数!很好!你能解释一下zip
在这里做什么吗?谢谢zip
同时迭代多个iterable(例如列表、迭代器)*df.apply
将产生N(N=len(df)
)个iterable,每个iterable包含2个元素zip
将同时在N行上迭代,因此它将生成由N个元素组成的2个iterables。您可以对此进行测试,例如zip(['a','b'],['c','d'],['e','f'])
将产生[('a','c','e'),('b','d','f')]
(基本上是转置)。请注意,我有意使用单词yield
,而不是return
,因为我们谈论的是迭代器(因此,将zip结果转换为一个列表:list(zip(['a','b',['c','d',['e','f'])
)