Найти самую большую строку в матрице с numpy (строка с наибольшей длиной) - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть массивный массив со строками и столбцами.Некоторые строки больше, чем другие.Мне нужно получить строку максимальной длины, то есть строку, которая имеет наибольшую длину.Я написал для этого простую функцию, но хотел, чтобы она была максимально быстрой, как быстрая.В настоящее время это выглядит следующим образом:

Пример массива:

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?

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019
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)

Если вы начинаете сlist, это хорошая идея, чтобы тщательно протестировать реализацию списка.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)
0 голосов
/ 20 февраля 2019

Не уверен, как вы можете сделать это быстрее.Я пытался использовать 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,00598 с

value_max_width_len заняло 0,00994 с

* Редактировать *

Как и предполагал @Mstaino, использование карты ускоряет этот код:

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

values_max_width заняло 0,00598с

значение_max_width_len заняло 0,00499 с

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...