我有一个类,该类通过比较不同的值返回一个值。该类是:
class feasible:
def __init__(self,old_difference, for_value, back_value, fall_back_value):
self.diff=abs(for_value-back_value)
for_diff=abs(for_value-fall_back_value)
back_diff=abs(back_value-fall_back_value)
if self.diff < old_difference:
self.value=(for_value+back_value)/2
elif for_diff<back_diff:
self.value=(for_value)
else:
self.value=(back_value)
如果输入是来自不同数据框架的列,我如何应用此类并返回值?
所有输入帧均采用以下格式:
x y theta
0 0.550236 -4.621542 35.071022
1 5.429449 -0.374795 74.884065
2 4.590866 -4.628868 110.697109
我尝试了以下操作,但由于涉及比较,因此返回错误(错误:系列的真值不明确)。
feasible_x=feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame.x=feasible_x.value
答案 0 :(得分:1)
当前,您的方法希望接收标量值,但是您将Pandas系列(即,数据帧的列)传递给该方法。因此,if
逻辑需要检查Series的每个元素(许多相同类型值的结构),而不是一个值。因此,您收到模棱两可的真实值的错误。熊猫新手经常会遇到来自通用Python的错误。 Pandas / Numpy与普通Python维护的对象模型不同。
要解决,因为您实际上是在使用条件逻辑来计算新字段,所以请考虑将所有Series参数绑定到一个数据帧中。然后,将if...elif...else
的常规Python构造替换为numpy.where
,该构造在跨诸如数组的高维对象上运行逻辑。
class feasible:
def __init__(self, old_difference, for_value, back_value, fall_back_value):
# HORIZONTAL MERGE (OUTER JOIN) ON INDEX
x_frame = (pd.concat([old_difference, for_value, back_value, fall_back_value], axis = 1)
.set_axis(['old_difference', 'for_value', 'back_value', 'fall_back_value'],
axis = 'columns', inplace = False)
)
# ASSIGN NEW CALCULATED COLUMNS
x_frame['diff'] = (x_frame['for_value'] - x_frame['back_value']).abs()
x_frame['for_diff'] = (x_frame['for_value'] - x_frame['fall_back_value']).abs()
x_frame['back_diff'] = (x_frame['back_value'] - x_frame['fall_back_value']).abs()
# ASSIGN FINAL SERIES BY NESTED CONDITIONAL LOGIC
self.value = np.where(x_frame['diff'] < x_frame['old_difference'],
(x_frame['for_value'] + x_frame['back_value'])/2,
np.where(x_frame['for_diff'] < x_frame['back_diff'],
x_frame['for_value'],
x_frame['back_value']
)
)
现在,取决于所有四个数据帧的行大小,必须处理结果的不同实现。具体来说,默认情况下,pd.concat
处的axis = 1
在join='outer'
上运行,因此所有行都保留在水平合并操作中,其中NaN
填充了不匹配的行。
如果 filler_frame (您打算添加一列的数据帧)等于所有行,则可以进行简单分配。
# IF filler_frame CONTAINS THE MOST ROWS (OR EQUIVALENT TO MOST) OF ALL FOUR DFs
feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame['x_new'] = feasible_x.value
如果不是新列的左联接,则需要 x_new 。下面将适用于所有情况,包括上面。
# IF filler_frame DOES NOT CONTAIN MOST ROWS OF ALL FOUR DFs
feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame = filler_frame.join(pd.Series(feasible_x.value).rename('x_new'), how = 'left')