【问题标题】:How do I make this function able to use a numpy array as an argument and return an array in python?如何使这个函数能够使用 numpy 数组作为参数并在 python 中返回一个数组?
【发布时间】:2020-02-02 07:13:41
【问题描述】:

如何使这个函数能够使用 numpy 数组作为参数并返回一个大小相同的数组,其中 tan() 在 python 中以元素方式应用? 我当前的代码如下所示,但它没有返回两个选项的完整数组。如何使用 tanc() 值创建输出数组?

def tanc(x):

    if x == 0:
        return 1
    else:
        return np.tan(x)/x

想要一个输出,例如: array([ 1.0, 0.27323654e+00, -4.89610183e-17])

【问题讨论】:

  • 查看np.where
  • @Mad Physicist 我收到一条错误消息,提示“布尔索引与第 0 维的索引数组不匹配;维数为 7,但对应的布尔维数为 3”

标签: python arrays numpy boolean masking


【解决方案1】:
def tanc(x):
    if x == 0:
        return 1
    else:
        return np.tan(x)/x

def return_array(some_array):
    return np.array(list(map(tanc, some_array)))

【讨论】:

  • 这将是非常低效的。通过这样做,您基本上放弃了 numpy 的所有功能。
  • 在 numpy 中是否有对应的地图?
  • 使用 NumPy,您通常使用 universal functions 或 NumPy 提供的其他功能,例如 advanced indexing(尤其是 boolean indexing)对整个数组或其维度进行操作。
  • Numpy 函数已经被向量化了:基本上,map 是内置在所有东西中的。 Ufuncs 也内置了累积和减少。
  • 本网站上通常不赞成仅使用代码的答案。您能否编辑您的答案以包含一些 cmets 或对您的代码的解释?解释应该回答这样的问题:它有什么作用?它是如何做到的?它去哪儿了?它如何解决OP的问题?见:How to anwser。谢谢!
【解决方案2】:

您可以使用numpy.where,并将where 参数用于np.dividenp.tan

np.where(cond, a, b) 给出一个数组,其中来自a 的值用于cond 的真实元素,b 的元素用于cond 的虚假元素。

np.dividenp.tanwhere 参数告诉他们只在另一个数组中为真的位置执行操作,而其他一些元素未初始化(所以它们可以是任何东西,但它没有没关系,因为我们不会在这里使用它们)。

nonzero = x != 0 # we only care about places where x isn't 0
# Get tan, then divide by x, but only where x is not 0
nonzero_tan = np.tan(x, where=nonzero)
nonzero_tanc = np.divide(nonzero_tan, x, where=nonzero)
# Where x is not zero, use tan(x)/x, and use 1 everywhere else
tanc = np.where(nonzero, nonzero_tanc, 1)

正如 hpaulj 在他们的评论中所建议的那样,您还可以通过使用 np.divideout 参数来定义输出数组的默认值来组合最后两个步骤:

nonzero = x != 0
nonzero_tan = np.tan(x, where=nonzero)
tanc = np.divide(nonzero_tan, x, out=np.ones_like(x), where=nonzero)

【讨论】:

  • 这是我第一次看到where 在 SO 上正确使用。没有计算错误,也没有重复工作。干得好
  • 您可以使用out 参数进一步加快速度。
  • @MadPhysicist 你可能可以,但除非速度是一个特别关注的问题,否则没有理由这样做。
  • 其他时候,当我使用where 参数进行探索时,我发现它最适合使用定义“默认”值(非位置)的out。如果没有 outufuncempty 数组开头。在这里,我认为在divide 中使用np.ones_like(x) 将替换最后一个where 语句。
  • @hpaulj 说得好;我已将其添加为我的答案的附录。
【解决方案3】:

使用掩码对每个元素的条件进行编码:

mask = (x != 0)

您可以对满足您条件的数据部分应用 numpy 操作:

output = np.zeros(x.shape, dtype=float)
output[~mask] = 1
output[mask] = tan(x[mask]) / x[mask]

一起(减少冗余操作):

def tanc(x):
    output = np.zeros(x.shape, dtype=float)
    output[~mask] = 1
    selected = x[mask]
    output[mask] = tan(selected) / selected
    return output

发布脚本

@jirasaimok's excellent answer 在我看来,是一种更优雅(如果你愿意的话,是 numpythonic)的方式来完成同样的事情:避免每个元素多次计算,并避免零除法。我建议他们的答案可以通过使用tandivideout 关键字来进一步增强,以避免分配和复制不必要的临时数组:

def tanc(x):
    mask = (x != 0)
    output = np.tan(x, where=mask)
    np.divide(output, x, where=mask, out=output)
    output[~mask] = 1
    return output

或者更好:

def tanc(x):
    mask = (x != 0)
    output = np.tan(x, where=mask, out=np.ones(x.shape, float))
    return np.divide(output, x, where=mask, out=output)

【讨论】:

    【解决方案4】:

    你可以这样做:

    def tanc(x):
        return np.sinc(x/np.pi)/np.cos(x)
    

    【讨论】:

    • 完美!太感谢了。这是一个我没有想到的非常简单的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多