嵌套numpy.where替代多条件pandas操作?

Log*_*vis 5 python numpy pandas

我有一个带条件列A和数字列B的Pandas DataFrame.

    A    B
1 'foo' 1.2
2 'bar' 1.3
3 'foo' 2.2
Run Code Online (Sandbox Code Playgroud)

我还有一个Python字典,它定义了B的范围,它表示给定每个A值的"成功".

mydict = {'foo': [1, 2], 'bar': [2, 3]}
Run Code Online (Sandbox Code Playgroud)

我想在数据框中创建一个新列'error'.它应该描述B的值落在A的可接受范围之外多远.如果A在该范围内,则该值应为零.

    A    B   error
1 'foo' 1.2   0
2 'bar' 1.3  -0.7
3 'foo' 2.2   0.2
Run Code Online (Sandbox Code Playgroud)

我不是一个完整的Pandas/Numpy新手,而且我在Python方面还不错,但事实证明这有点困难.我不想用iterrows()来做这件事,因为我明白它的计算成本很高,而且这会被调用很多.

我最终通过将lambda函数pandas.DataFrame.map()和嵌套的numpy.where()s与可选的x和y输入的给定值相结合来找出解决方案.

getmin = lambda x: mydict[x][0]
getmax = lambda x: mydict[x][1] 
df['error'] = np.where(df.B < dtfr.A.map(getmin),
                       df.B - df.A.map(getmin),
                       np.where(df.B > df.A.map(getmax),
                                df.B - df.A.map(getmax),
                                0
                                )
                       )
Run Code Online (Sandbox Code Playgroud)

它有效,但这不可能是最好的方法,对吗?我觉得我在滥用numpy.where(),不知道如何以非迭代的方式将数据帧的多个列中的值映射到lambda函数.(也是为了避免写出轻微粗糙的lambda函数).

我想有三个问题.

  1. 嵌套numpy.where()是否可以进行三项数组操作?
  2. 如何从两个数据帧列非迭代地映射到一个函数?
  3. 如果2)是可能的并且1)是可接受的,哪个更好?

max*_*moo 6

有关如何映射多个列的问题,请执行此操作

DataFrame.apply( , axis =1)
Run Code Online (Sandbox Code Playgroud)

对于你的问题,我认为你不需要这个,但我认为如果你通过几个步骤进行计算就更清楚了:

df['low'] = df.A.map(lambda x: mydict[x][0])
df['high'] = df.A.map(lambda x: mydict[x][1])
df['error'] = np.maximum(df.B - df.high, 0) + np.minimum(df.B - df.low, 0)
df
     A    B  low  high  error
1  foo  1.2    1     2    0.0
2  bar  1.3    2     3   -0.7
3  foo  2.2    1     2    0.2
Run Code Online (Sandbox Code Playgroud)


Ale*_*der 1

我相信下面的代码可以说更具可读性。

df['min'] = df.A.apply(lambda x: min(mydict[x]))
df['max'] = df.A.apply(lambda x: max(mydict[x]))
df['error'] = 0.
df.loc[df.B.gt(df['max']), 'error'] = df.B - df['max']
df.loc[df.B.lt(df['min']), 'error'] = df.B - df['min']
df.drop(['min', 'max'], axis=1, inplace=True)
>>> df
     A    B  error
1  foo  1.2    0.0
2  bar  1.3   -0.7
3  foo  2.2    0.2
Run Code Online (Sandbox Code Playgroud)

我不明白为什么你不能使用 numpy.where() 进行三条件数组操作,但你确实牺牲了简单性。