Python 在df.apply()中的自定义函数中传递DataFrame中的不同列
假设我有一个数据帧Python 在df.apply()中的自定义函数中传递DataFrame中的不同列,python,pandas,dataframe,Python,Pandas,Dataframe,假设我有一个数据帧df: x y z 0 1 2 3 1 4 5 6 2 7 8 9 df['xz'] = df.apply(func, axis=1) 我想有两个新列,分别是x*y和x*z: x y z xy xz 0 1 2 3 2 3 1 4 5 6 20 24 2 7 8 9 56 63 因此,我定义了一个函数func(仅举个例子),它将字符串'y'或字符串'z'作为参数,以指示要与列x相乘的列: def func(row, colName): return r
df
:
x y z
0 1 2 3
1 4 5 6
2 7 8 9
df['xz'] = df.apply(func, axis=1)
我想有两个新列,分别是x*y和x*z:
x y z xy xz
0 1 2 3 2 3
1 4 5 6 20 24
2 7 8 9 56 63
因此,我定义了一个函数func
(仅举个例子),它将字符串'y'
或字符串'z'
作为参数,以指示要与列x相乘的列:
def func(row, colName):
return row['x'] * row[colName]
并将该函数应用于数据帧df
:
x y z
0 1 2 3
1 4 5 6
2 7 8 9
df['xz'] = df.apply(func, axis=1)
显然,这里是错误的,因为我没有指定colName
,'y'
或'z'
。问题是,df.apply()
df['xz'] = df.apply(lambda x: func(x['x'], x[colName]), axis=1)
你的职能是:
def func(x, colName):
return x * colName
您可以将lambda函数用于指定列,但也需要更改func
:
def func(row, colName):
return row * colName
cols = ['y', 'z']
for c in cols:
df['x' + c] = df.apply(lambda x: func(x['x'], x[c]), axis=1)
def func(row, colName):
return row['x'] * row[colName]
cols = ['y', 'z']
for c in cols:
df['x' + c] = df.apply(lambda x: func(x, c), axis=1)
如果无法更改func
:
def func(row, colName):
return row * colName
cols = ['y', 'z']
for c in cols:
df['x' + c] = df.apply(lambda x: func(x['x'], x[c]), axis=1)
def func(row, colName):
return row['x'] * row[colName]
cols = ['y', 'z']
for c in cols:
df['x' + c] = df.apply(lambda x: func(x, c), axis=1)
您可以在听写理解中使用赋值来完成此操作
选项1
保持第一列固定:
def func(row, j):
return row['x'] * row[j]
cols = ['y', 'z']
df.assign(**{'x' + c : df.apply(func, args=c, axis=1) for c in cols})
x y z xy xz
0 1 2 3 2 3
1 4 5 6 20 24
2 7 8 9 56 63
选项2
两列都不固定的备选方案:
def func(row, i, j):
return row[i] * row[j]
pairs = [('x', 'y'), ('x', 'z')]
df.assign(**{''.join(p) : df.apply(func, args=p, axis=1) for p in pairs})
x y z xy xz
0 1 2 3 2 3
1 4 5 6 20 24
2 7 8 9 56 63
在pandas 0.22.0
中,我能够执行以下操作以获得您的预期输出:
df['xy'] = df.apply(func, axis=1, args='y')
df['xz'] = df.apply(func, axis=1, args='z')
pd.DataFrame.apply的docstring显示以下内容:
pd.DataFrame.apply(self, func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)
.
.
.
args : tuple; Positional arguments to pass to function in addition to the array/series
因此,您需要使用df.apply()
中的args
关键字参数将任何位置参数传递给func
,我认为eval
在这里是完美的
df['x*y'],df['x*z']=df.eval('x*y'),df.eval('x*z')
df
Out[14]:
x y z x*y x*z
0 1 2 3 2 3
1 4 5 6 20 24
2 7 8 9 56 63
我更喜欢第一个选项,但不太明白什么是'x'+c
。新列的名称是?@PacmanKX,确切地说,在那里命名列。这只是简单的字符串连接。这真的很有效!只有一个小问题,'x'+c
是列名吗?认为字符串可以用作列名。@PacmanKX-确切地说,它是列表理解,对于每个循环,都从cols
list返回值。所以在第一个循环中y
和第二个循环中z
他,很好:)很酷!谢谢真不错。如果这是OP的真实用例,它将最适合。伟大的解决方案!谢谢你的回答!没有更改原始的func
?我没有更改原始的func
定义。如果我的答案或其他答案有用,请不要忘记-单击答案旁边的复选标记(v
),将其从灰显切换为填充。接受的答案应该只有一个。