我有以下工作代码,可以创建一些简单的数学函数和一个具有多索引列的DataFrame。我想有条件地在它上面应用一些函数。
import pandas as pd
import numpy as np
# Simple maths functions ---
def add(scalars): return sum(scalars) #Adds every element in scalars
def sub(scalars): return (scalars[0] - sum(scalars[1:])) #First scalar value subtracted by the rest of the scalar list
def mul(scalars): return np.prod(scalars) #Multiplies every element in scalars
def divi(scalars): return (scalars[0] / np.prod(scalars[1:])) #First scalar value divided by the rest product of the scalar list# Create df ---
operatorList = [add, sub, mul, divi] # List of our maths functions
names = ['add', 'sub', 'mul', 'divi'] # List of the names of our maths functions
size = 4
tups = [('scalars', 'add', 'sc0'), ('scalars', 'add', 'sc1'), ('scalars', 'add', 'sc2'), ('scalars', 'sub', 'sc0'), ('scalars', 'sub', 'sc1'), ('scalars', 'mul', 'sc0'), ('scalars', 'mul', 'sc1'), ('scalars', 'mul', 'sc2'), ('scalars', 'divi', 'sc0'), ('scalars', 'divi', 'sc1'), ('operator', '', '')]
df = pd.DataFrame(columns=pd.MultiIndex.from_tuples(tups))
df['operatorIndex'] = np.random.randint(0, len(names), size)
df['operator'] = df['operatorIndex'].apply(lambda x: str(names[x]))
groupSize = 2
df['ID']=np.divmod(np.arange(len(df)),groupSize)[0]+1
df.set_index('ID', inplace=True)
df.sort_index(inplace=True)
for name in names:
df.loc[(df['operator'] == name), ('scalars', name, df.columns.levels[2])] = np.random.randint(0, 10)> df
scalars operator operatorIndex
add sub mul divi
sc0 sc1 sc2 sc0 sc1 sc0 sc1 sc2 sc0 sc1
ID
1 4 4 4 NaN NaN NaN NaN NaN NaN NaN add 0
1 NaN NaN NaN 7 7 NaN NaN NaN NaN NaN sub 1
2 NaN NaN NaN NaN NaN 3 3 3 NaN NaN mul 2
2 NaN NaN NaN 7 7 NaN NaN NaN NaN NaN sub 1如何创建一个名为Evaluation的新列,它是每个列的正确数学函数的结果?列operator告诉每一行需要应用哪个函数。
一个目标df示例如下所示:
> df
scalars operator operatorIndex Evaluation
add sub mul divi
sc0 sc1 sc2 sc0 sc1 sc0 sc1 sc2 sc0 sc1
ID
1 4 5 6 NaN NaN NaN NaN NaN NaN NaN add 0 15
1 NaN NaN NaN 7 2 NaN NaN NaN NaN NaN sub 1 5
2 NaN NaN NaN NaN NaN 1 2 3 NaN NaN mul 2 6
2 NaN NaN NaN 5 9 NaN NaN NaN NaN NaN sub 1 -4发布于 2021-11-20 22:58:25
这样就行了:
df['Evaluation'] = df['operatorIndex'].apply(lambda operatorIndex: operatorList[operatorIndex](df['scalars'][names[operatorIndex]].min()))虽然它只有在每个操作符只有一个条目时才能工作-如果一个操作在df中有多行,它将产生奇怪的结果。
您可以通过存储为每一行更新的全局计数器,并使用iloc按索引访问标量行来修复此问题:
rowCounter = -1
def func(operatorIndex):
global rowCounter
rowCounter += 1
return operatorList[operatorIndex](df['scalars'][names[operatorIndex]].iloc[rowCounter])
df['Evaluation'] = df['operatorIndex'].apply(func)发布于 2021-11-21 18:41:14
我设法改编了@user17242583的答案
df['Evaluation'] = df.apply(lambda row: operatorList[row['operatorIndex'].values[0]](row['scalars'][names[row['operatorIndex'].values[0]]].to_numpy()) , axis=1 )我不知道这对其他人是否有用,但这是给你的。
https://stackoverflow.com/questions/70050283
复制相似问题