如何根据条件有效地将函数应用于数组中的值?

时间:2017-04-26 12:08:21

标签: python arrays performance numpy vectorization

我有一个像这样的数组arorg

import numpy as np
arorg = np.array([[-1., 2., -4.], [0.5, -1.5, 3]])

和另一个看起来如下的数组values

values = np.array([1., 0., 2.])

values的条目数与arorg列相同。

现在我想对条目或arorg应用函数,具体取决于它们是正面还是负面:

def neg_fun(val1, val2):
    return val1 / (val1 + abs(val2))

def pos_fun(val1, val2):
    return 1. / ((val1 / val2) + 1.)

因此,val2arorgval1中的(绝对)值 - 这是棘手的部分 - 来自values;如果我将pos_funneg_fun应用于i中的arorg列,则val1应为values[i]

我目前实现如下:

ar = arorg.copy()

for (x, y) in zip(*np.where(ar > 0)):
    ar.itemset((x, y), pos_fun(values[y], ar.item(x, y)))

for (x, y) in zip(*np.where(ar < 0)):
    ar.itemset((x, y), neg_fun(values[y], ar.item(x, y)))

给了我想要的输出:

array([[ 0.5       ,  1.        ,  0.33333333],
       [ 0.33333333,  0.        ,  0.6       ]])

由于我必须经常进行这些计算,我想知道是否有更有效的方法来做到这一点。像

这样的东西
np.where(arorg > 0, pos_fun(xxxx), arorg)

会很棒,但我不知道如何正确传递参数(xxx)。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

正如问题中暗示的那样,这是使用np.where的。

首先,我们使用函数实现的直接转换来为正面和负面情况生成值/数组。然后,使用正值掩码,我们将使用np.where在这两个数组之间进行选择。

因此,实现将沿着这些方向发展 -

# Get positive and negative values for all elements
val1 = values
val2 = arorg
neg_vals = val1 / (val1 + np.abs(val2))
pos_vals = 1. / ((val1 / val2) + 1.)

# Get a positive mask and choose between positive and negative values 
pos_mask = arorg > 0
out = np.where(pos_mask, pos_vals, neg_vals)

答案 1 :(得分:1)

您不需要将函数应用于数组的压缩元素,您可以通过简单的数组操作和切片来完成相同的操作。

首先,获得正面和负面计算,保存为数组。然后创建一个零的返回数组(作为默认值),并使用posneg的布尔切片填充它:

import numpy as np
arorg = np.array([[-1., 2., -4.], [0.5, -1.5, 3]])
values = np.array([1., 0., 2.])

pos = 1. / ((values / arorg) + 1)
neg = values / (values + np.abs(arorg))

ret = np.zeros_like(arorg)
ret[arorg>0] = pos[arorg>0]
ret[arorg<=0] = neg[arorg<=0]

ret
# returns:
array([[ 0.5       ,  1.        ,  0.33333333],
       [ 0.33333333,  0.        ,  0.6       ]])

答案 2 :(得分:1)

public function getSendedRequests($broker_id) {
    $broker = User::where('broker_id', $broker_id)->lists('id');
    //my customer sended request
    $getUser = ProfileRequest::whereIn('requested_id', $broker)->lists('requested_id');
    $getReq = ProfileRequest::whereIn('requested_id', $broker)->lists('user_id');
    $sendUsers = $this->commonRequestQuery($getUser);
    $receivedUsers = $this->commonRequestQuery($getReq);
    return view('profilerequest')->with(['sendUsers' => $sendUsers->paginate(10), 'receivedUsers' => $receivedUsers->get(), 'title' => trans('messages.customer-sended-requests')]);
}

public function commonRequestQuery($values) {
    return DB::table('users')
        ->leftJoin('basic_informations', 'users.id', '=', 'basic_informations.user_id')
        ->leftJoin('physical_attributes', 'users.id', '=', 'physical_attributes.user_id')
        ->leftJoin('religion_and_ethnicity', 'users.id', '=', 'religion_and_ethnicity.user_id')
        ->leftJoin('occupational_attributes', 'users.id', '=', 'occupational_attributes.user_id')
        ->leftJoin('personal_interests', 'users.id', '=', 'personal_interests.user_id')
        ->select('users.id', 'users.user_name', 'users.email', 'users.gender', 'basic_informations.age', 'basic_informations.unique_id', 'basic_informations.mother_tongue', 'religion_and_ethnicity.religion_id', 'religion_and_ethnicity.caste_id', 'occupational_attributes.education_id', 'occupational_attributes.occupation_id')
        ->whereNotNull('basic_informations.user_id')
        ->whereNotNull('physical_attributes.user_id')
        ->whereNotNull('religion_and_ethnicity.user_id')
        ->whereNotNull('occupational_attributes.user_id')
        ->whereIn('users.id', $values);
}