假设我有一个df,它的列是" ID " " col_1 " " col_2 "我定义了一个函数:

F = x, y: my_function_expression。

现在我想应用f到df的两个列'col_1', 'col_2'来逐个元素计算一个新列'col_3',有点像:

df['col_3'] = df[['col_1','col_2']].apply(f)  
# Pandas gives : TypeError: ('<lambda>() takes exactly 2 arguments (1 given)'

怎么办?

**添加详细示例如下***

import pandas as pd

df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']

def get_sublist(sta,end):
    return mylist[sta:end+1]

#df['col_3'] = df[['col_1','col_2']].apply(get_sublist,axis=1)
# expect above to output df as below 

  ID  col_1  col_2            col_3
0  1      0      1       ['a', 'b']
1  2      2      4  ['c', 'd', 'e']
2  3      3      5  ['d', 'e', 'f']

当前回答

另一个选项是df.itertuples()(通常比df.iterrows()更快,由文档和用户测试推荐):

import pandas as pd

df = pd.DataFrame([range(4) for _ in range(4)], columns=list("abcd"))

df
    a   b   c   d
0   0   1   2   3
1   0   1   2   3
2   0   1   2   3
3   0   1   2   3


df["e"] = [sum(row) for row in df[["b", "d"]].itertuples(index=False)]

df
    a   b   c   d   e
0   0   1   2   3   4
1   0   1   2   3   4
2   0   1   2   3   4
3   0   1   2   3   4

因为itertuples返回一个namedtuples的Iterable,你可以通过列名(又名点表示法)和索引来访问元组元素:

b, d = row
b = row.b
d = row[1]

其他回答

一个有趣的问题!我的回答如下:

import pandas as pd

def sublst(row):
    return lst[row['J1']:row['J2']]

df = pd.DataFrame({'ID':['1','2','3'], 'J1': [0,2,3], 'J2':[1,4,5]})
print df
lst = ['a','b','c','d','e','f']

df['J3'] = df.apply(sublst,axis=1)
print df

输出:

  ID  J1  J2
0  1   0   1
1  2   2   4
2  3   3   5
  ID  J1  J2      J3
0  1   0   1     [a]
1  2   2   4  [c, d]
2  3   3   5  [d, e]

我将列名更改为ID,J1,J2,J3,以确保ID < J1 < J2 < J3,因此列以正确的顺序显示。

再简单说一下:

import pandas as pd

df = pd.DataFrame({'ID':['1','2','3'], 'J1': [0,2,3], 'J2':[1,4,5]})
print df
lst = ['a','b','c','d','e','f']

df['J3'] = df.apply(lambda row:lst[row['J1']:row['J2']],axis=1)
print df

您正在寻找的方法是Series.combine。 然而,在数据类型方面似乎需要多加注意。 在您的示例中,您会(就像我在测试答案时那样)天真地调用

df['col_3'] = df.col_1.combine(df.col_2, func=get_sublist)

但是,这会抛出错误:

ValueError: setting an array element with a sequence.

我最好的猜测是,它似乎期望结果与调用方法的系列(df。col_1这里)。然而,以下工作:

df['col_3'] = df.col_1.astype(object).combine(df.col_2, func=get_sublist)

df

   ID   col_1   col_2   col_3
0   1   0   1   [a, b]
1   2   2   4   [c, d, e]
2   3   3   5   [d, e, f]

我相信这不会像使用Pandas或Numpy操作的解决方案那么快,但如果你不想重写你的函数,你可以使用map。使用原始示例数据-

import pandas as pd

df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']

def get_sublist(sta,end):
    return mylist[sta:end+1]

df['col_3'] = list(map(get_sublist,df['col_1'],df['col_2']))
#In Python 2 don't convert above to list

我们可以通过这种方式向函数传递任意数量的参数。输出就是我们想要的

ID  col_1  col_2      col_3
0  1      0      1     [a, b]
1  2      2      4  [c, d, e]
2  3      3      5  [d, e, f]

另一个选项是df.itertuples()(通常比df.iterrows()更快,由文档和用户测试推荐):

import pandas as pd

df = pd.DataFrame([range(4) for _ in range(4)], columns=list("abcd"))

df
    a   b   c   d
0   0   1   2   3
1   0   1   2   3
2   0   1   2   3
3   0   1   2   3


df["e"] = [sum(row) for row in df[["b", "d"]].itertuples(index=False)]

df
    a   b   c   d   e
0   0   1   2   3   4
1   0   1   2   3   4
2   0   1   2   3   4
3   0   1   2   3   4

因为itertuples返回一个namedtuples的Iterable,你可以通过列名(又名点表示法)和索引来访问元组元素:

b, d = row
b = row.b
d = row[1]

我要投票支持np。vectorize。它允许你只拍摄x个列,而不处理函数中的数据帧,所以它非常适合你不控制的函数,或者做一些像发送2列和一个常数到一个函数(即col_1, col_2, 'foo')。

import numpy as np
import pandas as pd

df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']

def get_sublist(sta,end):
    return mylist[sta:end+1]

#df['col_3'] = df[['col_1','col_2']].apply(get_sublist,axis=1)
# expect above to output df as below 

df.loc[:,'col_3'] = np.vectorize(get_sublist, otypes=["O"]) (df['col_1'], df['col_2'])


df

ID  col_1   col_2   col_3
0   1   0   1   [a, b]
1   2   2   4   [c, d, e]
2   3   3   5   [d, e, f]