【问题标题】:Reassigning numpy.array()重新分配 numpy.array()
【发布时间】:2020-11-28 06:42:40
【问题描述】:

在下面的代码中,我可以轻松地将数组['a','b','a','c','b','b','c','a'] 简化为二进制数组[0 1 0 1 1 1 1 0],从而得到'a' -> 0'b','c' -> 1。如何在不使用forif-else 的情况下将其转换为三元数组以便'a' -> 0'b' -> 1'c' -> 2?谢谢。

import numpy as np
x = np.array(['a', 'b', 'a', 'c', 'b', 'b', 'c', 'a'])
y = np.where(x=='a', 0, 1)
print(y)

【问题讨论】:

    标签: python arrays numpy numpy-ndarray


    【解决方案1】:

    通过做:

    np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))
    

    请注意,这会将所有非“a”或“b”的字符更改为 2。我假设您只有一个包含 a、b 和 c 的数组。

    【讨论】:

    • 您应该使用np.select 来获得更多的二元结果。
    【解决方案2】:

    一个更具扩展性的版本是使用转换字典:

    my_dict = {'a':0, 'b':1, 'c':2}
    x = np.vectorize(my_dict.get)(x)
    

    输出:

    [0 1 0 2 1 1 2 0]
    

    另一种方法是:

    np.select([x==i for i in ['a','b','c']], np.arange(3))
    

    对于小字典@ypno 的回答会更快。对于更大的字典,请使用此答案。


    时间比较

    三进制字母

    lst = ['a','b','c']
    my_dict = {k: v for v, k in enumerate(lst)}
    
    #@Ehsan's solution1
    def m1(x):
      return np.vectorize(my_dict.get)(x)
    
    #@ypno's solution
    def m2(x):
      return np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))
    
    #@SteBog's solution
    def m3(x):
      y = np.where(x=='a', 0, x)
      y = np.where(x=='b', 1, y)
      y = np.where(x=='c', 2, y)
      return y.astype(np.integer)
    
    #@Ehsan's solution 2 (also suggested by user3483203 in comments)
    def m4(x):
       return np.select([x==i for i in lst], np.arange(len(lst)))
    
    #@juanpa.arrivillaga's solution suggested in comments
    def m5(x):
      return np.array([my_dict[i] for i in x.tolist()])
    
    in_ = [np.random.choice(lst, size = n) for n in [10,100,1000,10000,100000]]
    

    8 个字母的相同分析

    lst = ['a','b','c','d','e','f','g','h']
    

    【讨论】:

    • 为什么要使用np.vectorize?真的应该避免。几乎可以肯定,np.array([my_dict[x] for x in array.tolist()]) 会更快。
    • @juanpa.arrivillaga 谢谢你的建议。您能否提供更多信息,说明为什么 确实应该避免这种情况。几乎可以肯定?我不知道实现细节,但如果你认为它在 Numpy 中的实现不好,也许你可以将它提交给 Numpy 开发人员。但是,一个个人的答案是主观的可读性。另一个是 np.vectorize 对于更大的数组似乎比列表理解更快。我将添加时间比较以便更好地判断。谢谢。
    • 直接来自文档:“提供 vectorize 函数主要是为了方便,而不是为了性能。实现本质上是一个 for 循环。”
    • @juanpa.arrivillaga 很有趣。感谢您的答复。请查看我更新的时间分析。对于较大的数组,似乎矢量化稍微快一些。除非我遗漏了什么,否则向量化和简单循环似乎存在某种优化差异。
    • 可能是转换为列表的开销。如果我真的这样做,我就不会使用 numpy.ndarray 开始。不用.tolist() 试试,然后用常规列表试试,我打赌你会看到,用列表理解会更快。
    【解决方案3】:
    import numpy as np
    x = np.array(['a', 'b', 'a', 'c', 'b', 'b', 'c', 'a'])
    y = np.where(x=='a', 0, x)
    y = np.where(x=='b', 1, y)
    y = np.where(x=='c', 2, y)
    print(y)
    

    【讨论】:

    • 这会将数组的 dtype 保持为字符串。因此,我认为您的输出将是数字字符串而不是整数。最后使用y.astype(np.integer)进行转换。
    • 所提供的答案被标记为低质量帖子以供审核。以下是How do I write a good answer? 的一些指南。这个提供的答案可以从解释中受益。仅代码答案不被视为“好”答案。来自评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    相关资源
    最近更新 更多