【问题标题】:Find largest row in a matrix with numpy (row with highest length)使用 numpy 查找矩阵中的最大行(长度最长的行)
【发布时间】:2019-02-20 19:26:21
【问题描述】:

我有一个包含行和列的庞大数组。有些行比其他行大。我需要获取最大长度行,即长度最长的行。我为此编写了一个简单的函数,但我希望它尽可能快,就像 numpy fast 一样。目前,它看起来像这样:

示例数组:

values = [
    [1,2,3],
    [4,5,6,7,8,9],
    [10,11,12,13]
]

def values_max_width(values):
    max_width = 1
    for row in values:
        if len(row) > max_width:
            max_width = len(row)
    return max_width

有没有办法用 numpy 来完成这个?

【问题讨论】:

  • 如果你只想要最大长度,你总是可以在纯 python 中做max(map(len, values))。如果您想要与最大长度对应的行,请使用 values[np.fromiter(map(len, values), int).argmax()]
  • 您的行长度不同,因此您无法将完整数组放入 numpy,因为它不支持锯齿状数组。您将无法仅使用 numpy 来实现这一点。您将不得不在工作流程的至少一部分中使用 python 内置函数,老实说,还不如留在那里。
  • 谢谢,姆斯坦诺。在我做的测试中,比较了我所有的方法,你的是最快的。

标签: python numpy


【解决方案1】:

不确定如何让它更快。我尝试在每个项目的长度上使用 np.max,但这需要更长的时间:

import numpy as np
import time

values = []
for k in range(100000):
    values.append(list(np.random.randint(100, size=np.random.randint(1000))))


def timeit(func):
    def wrapper(*args, **kwargs):
        now = time.time()
        retval = func(*args, **kwargs)
        print('{} took {:.5f}s'.format(func.__name__, time.time() - now))
        return retval
    return wrapper

@timeit
def values_max_width(values):
    max_width = 1
    for row in values:
        if len(row) > max_width:
            max_width = len(row)
    return max_width


@timeit
def value_max_width_len(values):
    return np.max([len(l) for l in values])


values_max_width(values)
value_max_width_len(values)

values_max_width 耗时 0.00598s

value_max_width_len 耗时 0.00994s

* 编辑 *

正如@Mstaino 建议的那样,使用 map 确实可以让这段代码更快:

@timeit
def value_max_width_len(values):
    return max(map(len, values))

values_max_width 耗时 0.00598s

value_max_width_len 耗时 0.00499s

【讨论】:

  • 我明白,并感谢您的努力。根据@Mstaino 的推荐,到目前为止我得到的最优化是map
  • np.max 比 Python max 慢 - 因为它首先必须将列表转换为数组。
【解决方案2】:
In [261]: values = [ 
     ...:     [1,2,3], 
     ...:     [4,5,6,7,8,9], 
     ...:     [10,11,12,13] 
     ...: ] 
     ...:                                                                       
In [262]:                                                                       
In [262]: values                                                                
Out[262]: [[1, 2, 3], [4, 5, 6, 7, 8, 9], [10, 11, 12, 13]]
In [263]: def values_max_width(values): 
     ...:     max_width = 1 
     ...:     for row in values: 
     ...:         if len(row) > max_width: 
     ...:             max_width = len(row) 
     ...:     return max_width 
     ...:                                                                       
In [264]: values_max_width(values)                                              
Out[264]: 6
In [265]: [len(v) for v in values]                                              
Out[265]: [3, 6, 4]
In [266]: max([len(v) for v in values])                                         
Out[266]: 6
In [267]: np.max([len(v) for v in values])                                      
Out[267]: 6

您的循环和列表理解的速度相似,np.max 要慢得多 - 它必须首先将列表转换为数组。

In [268]: timeit max([len(v) for v in values])                                  
656 ns ± 16.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [269]: timeit np.max([len(v) for v in values])                               
13.9 µs ± 181 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [271]: timeit values_max_width(values)                                       
555 ns ± 13 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

如果您从列表开始,最好彻底测试列表实现。 numpy 在编译数组时速度很快,但从列表创建数组很耗时。

直接从values 创建一个数组并没有多大帮助。对象 dtype 数组中的结果:

In [272]: arr = np.array(values)                                                
In [273]: arr                                                                   
Out[273]: 
array([list([1, 2, 3]), list([4, 5, 6, 7, 8, 9]), list([10, 11, 12, 13])],
      dtype=object)

这种数组上的数学是命中注定的,而且总是比纯数值数组上的数学慢。我们可以对这样的数组进行迭代,但迭代比列表要慢。

In [275]: values_max_width(arr)                                                 
Out[275]: 6
In [276]: timeit values_max_width(arr)                                          
1.3 µs ± 8.27 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

【讨论】:

    猜你喜欢
    • 2011-03-22
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 2018-12-21
    • 1970-01-01
    • 2014-08-03
    • 2011-03-20
    相关资源
    最近更新 更多