Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 嵌套numpy的替代方案。多条件操作在哪里?_Python_Numpy_Pandas - Fatal编程技术网

Python 嵌套numpy的替代方案。多条件操作在哪里?

Python 嵌套numpy的替代方案。多条件操作在哪里?,python,numpy,pandas,Python,Numpy,Pandas,我有一个带有条件列a和数字列B的数据帧 A B 1 'foo' 1.2 2 'bar' 1.3 3 'foo' 2.2 我还有一个Python字典,它定义了B的范围,在给定a的每个值时表示“成功” mydict = {'foo': [1, 2], 'bar': [2, 3]} 我想在数据帧中创建一个新列“error”。它应该描述B的值下降到A的可接受范围之外有多远。如果A在范围内,则该值应为零 A B error 1 'foo' 1.2 0 2 'bar'

我有一个带有条件列a和数字列B的数据帧

    A    B
1 'foo' 1.2
2 'bar' 1.3
3 'foo' 2.2
我还有一个Python字典,它定义了B的范围,在给定a的每个值时表示“成功”

mydict = {'foo': [1, 2], 'bar': [2, 3]}
我想在数据帧中创建一个新列“error”。它应该描述B的值下降到A的可接受范围之外有多远。如果A在范围内,则该值应为零

    A    B   error
1 'foo' 1.2   0
2 'bar' 1.3  -0.7
3 'foo' 2.2   0.2
我不是一个完全的熊猫/小矮人新手,而且我在Python方面有点不错,但事实证明这有点困难。我不想用iterrows()来做这件事,因为我知道这在计算上很昂贵,而且这会被大量调用

我最终找到了一个解决方案,将lambda函数、pandas.DataFrame.map()和嵌套的numpy.where()与可选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
                                )
                       )
getmin=lambda x:mydict[x][0]
getmax=lambda x:mydict[x][1]
df['error']=np.where(df.Bdf.A.map(getmax),
df.B-df.A.map(getmax),
0
)
)
这是可行的,但这不可能是最好的方法,对吧?我觉得我在滥用numpy.where()来四处游荡,不知道如何以非迭代的方式将数据帧的多列值映射到lambda函数。(还要避免编写稍微粗糙的lambda函数)

大概有三个问题吧

  • 可以为三条件数组操作嵌套numpy.where()s吗
  • 如何以非迭代方式将两个数据帧列映射到一个 功能
  • 如果2)是可能的,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
    

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

    关于如何映射多个列的问题,请使用

    DataFrame.apply( , axis =1)
    
    对于你的问题,我认为你不需要这个,但我认为如果你分几个步骤进行计算,会更清楚:

    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
    

    需要注意的是,您已经破坏了df的
    max
    min
    方法。仅供参考的方法根本不会被破坏(除非您明确指定给它们),例如
    df.min=..
    。一个集合列独立于此HMM不知道。。。那么这是否意味着您总是使用dict索引表示法而不是方法表示法来引用列?
    df['max']=…
    很好,不会破坏数据帧的
    max
    函数<相比之下,code>df.max=…,会破坏函数。您应该始终使用括号表示法进行设置。引用时使用括号更安全(以避免此问题),但点表示法纯粹是方便的,只要不使用DataFrame的某个命名属性或方法,就可以正常工作。FWIW,我花了一段时间才弄清楚这到底是在做什么。可以肯定,这主要与我对df.loc[行索引器、列索引器]不熟悉有关。所以,谢谢你让我知道这一点。就loc而言,现在我已经加入了,我同意这似乎比maxymoo的答案更具可读性+1关于嵌套,一种选择是只使用顺序
    np.where()
    s,在我看来更容易阅读。此外,我认为@unutbu或@DSM在过去一个月左右(使用不同的numpy函数)显示了多个
    np.where(),我认为你这样做很好。我认为这是一种非常有效的方法,它是否是最具可读性的方法在某种程度上取决于偏好。我认为这是其中的一种情况,因为pandas的隐式矢量化使得它很难像编写显式循环那样可读编码——当然,这在pandas中通常是要避免的。第三行非常聪明。我应该考虑利用df.B永远不会同时(大于A的最大值)和(小于A的最小值)的事实。像大多数“相当聪明”的代码一样,它可能需要注释来解释到底发生了什么,但是。。。干得好+1.