如何使用 pandas 中的多列映射函数?
How to map a function using multiple columns in pandas?
我已经查看了 map、apply、mapapply 和 combine,但似乎找不到执行以下操作的简单方法:
我有一个包含 10 列的数据框。我需要将其中三个传递给一个函数,该函数接受标量和 returns 一个标量 ...
some_func(int a, int b, int c) returns int d
我想应用它并使用结果在数据框中创建一个新列。
df['d'] = some_func(a = df['a'], b = df['b'], c = df['c'])
我发现的所有解决方案似乎都建议重写 some_func 以使用系列而不是标量,但这是不可能的,因为它是另一个包的一部分。如何优雅地执行上述操作?
我正在使用以下内容:
df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']))
似乎运行良好,但如果其他人有更好的解决方案,请告诉我。
使用pd.DataFrame.apply()
,如下:
df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']), axis=1)
注意:如 @ashishsingal asked about columns, the axis
argument should be provided with a value of 1, as the default is 0 (as in the documentation 并在下方复制)。
axis : {0 or ‘index’, 1 or ‘columns’}, default 0
- 0 or ‘index’: apply function to each column
- or ‘columns’: apply function to each row
如果它是一个非常简单的函数,例如基于简单算术的函数,很可能可以对其进行矢量化。例如,可以直接从列中进行线性组合:
df["d"] = w1*df["a"] + w2*df["b"] + w3*["c"]
其中 w1、w2、w3 是标量权重。
这么老的问题有什么价值;我发现将函数参数压缩成元组,然后将函数作为列表理解来应用比使用 df.apply
快得多。例如:
import pandas as pd
# Setup:
df = pd.DataFrame(np.random.rand(10000, 3), columns=list("abc"))
def some_func(a, b, c):
return a*b*c
# Using apply:
%timeit df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']), axis=1)
每个循环 222 毫秒 ± 63.8 毫秒(7 次运行的平均值 ± 标准偏差,每次 1 个循环)
# Using tuples + list comprehension:
%timeit df["d"] = [some_func(*a) for a in tuple(zip(df["a"], df["b"], df["c"]))]
每个循环 8.07 毫秒 ± 640 微秒(7 次运行的平均值 ± 标准偏差,每次 100 次循环)
我使用的 map 与列表理解一样快(比应用快得多):
df['d'] = list(map(some_func, df['a'], df['b'], df['c']))
我机器上的例子:
import pandas as pd
# Setup:
df = pd.DataFrame(np.random.rand(10000, 3), columns=list("abc"))
def some_func(a, b, c):
return a*b*c
# Using apply:
%timeit df['d'] = df.apply(lambda x: some_func(a = x['a'],
b = x['b'], c = x['c']), axis=1)
每个循环 130 毫秒 ± 1.11 毫秒(7 次运行的平均值 ± 标准偏差,每次 10 次循环)
%timeit df['d'] = list(map(some_func, df['a'], df['b'], df['c']))
每个循环 3.91 ms ± 22.9 µs(7 次运行的平均值 ± 标准偏差,每次 100 次循环)
我已经查看了 map、apply、mapapply 和 combine,但似乎找不到执行以下操作的简单方法:
我有一个包含 10 列的数据框。我需要将其中三个传递给一个函数,该函数接受标量和 returns 一个标量 ...
some_func(int a, int b, int c) returns int d
我想应用它并使用结果在数据框中创建一个新列。
df['d'] = some_func(a = df['a'], b = df['b'], c = df['c'])
我发现的所有解决方案似乎都建议重写 some_func 以使用系列而不是标量,但这是不可能的,因为它是另一个包的一部分。如何优雅地执行上述操作?
我正在使用以下内容:
df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']))
似乎运行良好,但如果其他人有更好的解决方案,请告诉我。
使用pd.DataFrame.apply()
,如下:
df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']), axis=1)
注意:如 @ashishsingal asked about columns, the axis
argument should be provided with a value of 1, as the default is 0 (as in the documentation 并在下方复制)。
axis : {0 or ‘index’, 1 or ‘columns’}, default 0
- 0 or ‘index’: apply function to each column
- or ‘columns’: apply function to each row
如果它是一个非常简单的函数,例如基于简单算术的函数,很可能可以对其进行矢量化。例如,可以直接从列中进行线性组合:
df["d"] = w1*df["a"] + w2*df["b"] + w3*["c"]
其中 w1、w2、w3 是标量权重。
这么老的问题有什么价值;我发现将函数参数压缩成元组,然后将函数作为列表理解来应用比使用 df.apply
快得多。例如:
import pandas as pd
# Setup:
df = pd.DataFrame(np.random.rand(10000, 3), columns=list("abc"))
def some_func(a, b, c):
return a*b*c
# Using apply:
%timeit df['d'] = df.apply(lambda x: some_func(a = x['a'], b = x['b'], c = x['c']), axis=1)
每个循环 222 毫秒 ± 63.8 毫秒(7 次运行的平均值 ± 标准偏差,每次 1 个循环)
# Using tuples + list comprehension:
%timeit df["d"] = [some_func(*a) for a in tuple(zip(df["a"], df["b"], df["c"]))]
每个循环 8.07 毫秒 ± 640 微秒(7 次运行的平均值 ± 标准偏差,每次 100 次循环)
我使用的 map 与列表理解一样快(比应用快得多):
df['d'] = list(map(some_func, df['a'], df['b'], df['c']))
我机器上的例子:
import pandas as pd
# Setup:
df = pd.DataFrame(np.random.rand(10000, 3), columns=list("abc"))
def some_func(a, b, c):
return a*b*c
# Using apply:
%timeit df['d'] = df.apply(lambda x: some_func(a = x['a'],
b = x['b'], c = x['c']), axis=1)
每个循环 130 毫秒 ± 1.11 毫秒(7 次运行的平均值 ± 标准偏差,每次 10 次循环)
%timeit df['d'] = list(map(some_func, df['a'], df['b'], df['c']))
每个循环 3.91 ms ± 22.9 µs(7 次运行的平均值 ± 标准偏差,每次 100 次循环)