2016-09-07 50 views
0

我知道这个主题有很多问题,但没有一个建议的答案似乎在这种情况下工作,我认为这是微不足道的,但现在已经杀了我2天了。使用函数从大熊猫的旧列值逐行计算新的列值

这是我第一次使用熊猫来处理眼动仪的导出文件。导出文件包含50列左右,其中2个包含瞳孔扩张措施PupilLeft和PupilRight。我想创建一个新的列PupilAvg,它将两者平均。当眼动仪无法读取一个或两个瞳孔时,它会记录-1。由于所需的逻辑很简单,但似乎对拉姆达有点长,我写了一个函数来为我的新列返回值:

def getEyeAvg(left, right): 
    # calcs avg for Left and Right where one or both may be missing (= -1) 
    if left == -1 and right == -1: return np.nan 
    if left == -1: return right 
    if right == -1: return left 
    return (left + right)/2.0 

这里的数据帧的实例版本:

In[25]: dfd = pd.DataFrame.from_items([('PupilLeft', [3., -1., 4., -1]), ('PupilRight', [4., 4., -1., -1])]) 

In[26]: dfd 
Out[26]: 
    PupilLeft PupilRight 
0  3.0   4.0 
1  -1.0   4.0 
2  4.0  -1.0 
3  -1.0  -1.0 

我要PupilRight后插入我的新列,所以我尽量命令:

In[27]: dfd.insert(2, 'PupilAvg', getEyeAvg(dfd.PupilLeft, dfd.PupilRight)) 

我期待PupilAvg是:

PupilLeft PupilRight PupilAvg 
0  3.0   4.0  3.5 
1  -1.0   4.0  4.0 
2  4.0  -1.0  4.0 
3  -1.0  -1.0  NaN 

当然,这并不工作,我得到

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). 

我见过问过这个问题的变化一遍又一遍,似乎每个答案使用了一些不同的“绝招”,这似乎令人费解给我,我的相对初学者地位。例如,我不希望'any'和'all'rows left == -1,我只想要当前行,但这似乎是pandas发现很难处理的请求。

这将是令人难以置信的有益的,如果有人可以提供这个问题,这基本上可以归结为

“我想用一个函数来计算使用来自其他值的新列值的明确通用的解决方案而不是一次一个地完成,你知道,就像在Excel中一样,是否有一种简单而通用的方法来实现这一点?“

对于像我这样试图从Excel解决方案转换到python/pandas的人来说,这特别困难,因为Excel自然是逐行的。您只需在第一行单元格中输入一个公式,并将其全部复制到列中。显然,这种思维模式让我对熊猫没有足够的准备。

回答

0

有一个简单的方法来实现您的目标,而整个列操作。

dfd.replace({-1:np.nan}, inplace=True) 
dfd['PupilAvg'] = dfd.mean(axis=1) 

如果由于某种原因需要保留原来的-1值,只需先复制它们,然后继续。有了明确的nan值,熊猫的一切都变得更容易。

您的原始代码失败,因为您将整列数据传递到getEyeAvg。在你的例子中,它试图评估pd.DataFrame.from_items([('PupilLeft',[3.,-1。,4.,-1])== -1,而不是3. == 1.在整个列一次是熊猫的默认模式,所以它需要一种新的思维方式,没有任何一种最好的方式来做到这一点,因为最有意义的方法来自Excel(直接通过行循环)索引或使用df.apply(lambda,axis = 1))比使用整列更慢。

+0

伟大的解决方案。两个后续问题。如何将dfd.replace限制为仅用于我的公式中的两列?我可能在50列出口数据的其他地方有-1,我不想惹这些。在同一笔记中,我怎样才能限制dfd.mean函数只计算来自两个源列的平均值,而不是在其他列的同一行中包含所有其他数值?谢谢! 。 –

+0

'DFD [[ 'PupilLeft', 'PupilRight']] = DFD [[ 'PupilLeft', 'PupilRight']]代替({ - 1:np.nan})' 然后 'DFD [” PupilAvg'] = dfd [[''PupilLeft','PupilRight']]。mean(axis = 1)' –