说我有一个数据框df
:
x y z
0 1 2 3
1 4 5 6
2 7 8 9
我想要两个新的列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
:
df['xz'] = df.apply(func, axis=1)
显然这里错了,因为我没有指定colName
,'y'
或'z'
。问题是,df.apply()
只是取了函数名,我怎么告诉它接受这两个参数?
答案 0 :(得分:4)
我认为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
答案 1 :(得分:3)
您可以使用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)
如果无法更改func
:
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)
print (df)
x y z xy xz
0 1 2 3 2 3
1 4 5 6 20 24
2 7 8 9 56 63
答案 2 :(得分:3)
您可以在 dict comprehension 中使用assign
执行此操作。
选项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
答案 3 :(得分:0)
一种可能的解决方案:
df['xz'] = df.apply(lambda x: func(x['x'], x[colName]), axis=1)
你的职能将成为:
def func(x, colName):
return x * colName
答案 4 :(得分:0)
在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
的文档字符串显示以下内容:
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
因此您需要使用func
args
关键字参数将任何位置参数传递给df.apply()